При кодировании я сталкиваюсь с ошибкой ConcurrentModificationException
.
Чтобы избежать этого, я использую логическое значение, чтобы определить, когда я использую коллекцию виновных, и если я пытаюсь изменить ее, когда она используется в другом потоке, я просто используйте while
l oop с Thread.sleep()
, но моя IDE (Intelij) говорит мне, что это плохо. После некоторого исследования я обнаружил, что это фактически плохо!
Я также обнаружил, что правильный способ заменить это - использовать систему ожидания / уведомления. Однако я совершенно не знаю, как это сделать.
Вот код моего класса, поэтому можете ли вы сказать, как я могу правильно реализовать ожидание / уведомление?
Я не новичок в java, но я действительно не знаю, как работать с торговлей, так как я никогда этому не учился и никогда не использую потоки. (Да, я знаю, что Swing использует потоки, но сам я этого никогда не делал.)
public class BoardRenderer extends JPanel implements BoardEventListener {
protected TreeSet<AbstractCell> cells = new TreeSet<>();
protected int boardWidth = -1, boardHeight = -1;
protected int lineSize=0,margin=3,outerBorder = 5;
// i use this boolean to prevent a ConcurrentModificationException
protected boolean rendering = false;
@Override
protected void paintComponent(Graphics g) {
rendering = true;
// size of cell in x and y
int cellY = (getHeight()-2*outerBorder)/getBoardHeight();
int cellX = (getWidth()-2*outerBorder)/getBoardWidth();
// as we want our cells to be square we keep the min of cellX and cellY
// we subtract the space taken by a line between two cells
int cellSize = Math.min(cellX,cellY) - lineSize;
// the size in px of where the cells are draw
int boardDrawWidth = getBoardWidth()*(cellSize);
int boardDrawHeight = getBoardHeight()*(cellSize);
// offset for centering where the cells are draw
int offsetX = (getWidth() -boardDrawWidth)/2;
int offsetY = (getHeight() -boardDrawHeight)/2 ;
// we erase any previous thing that were draw there
g.setColor(Color.WHITE);
g.fillRect(getX(),getY(),getWidth(),getHeight());
// we draw borders
g.setColor(Color.BLACK);
// top left to top right
g.fillRect(offsetX - outerBorder,offsetY - outerBorder,outerBorder,boardDrawHeight + 2*outerBorder);
// top left to bottom left
g.fillRect(offsetX - outerBorder,offsetY - outerBorder,boardDrawWidth + 2*outerBorder,outerBorder);
// bottom left to bottom right
g.fillRect(offsetX - outerBorder,getHeight() - offsetY,boardDrawWidth + 2*outerBorder,outerBorder);
// top right to bottom right
g.fillRect(getWidth() - offsetX,offsetY - outerBorder,outerBorder,boardDrawWidth + 2*outerBorder);
CellRenderer cellRenderer = new CellRenderer(cellSize,margin,lineSize,offsetX,offsetY);
for( AbstractCell c: cells){
cellRenderer.renderCell(c,g);
}
rendering = false;
}
@Override
public void boardResize(BoardEvent e) {
boardWidth = e.getWidth();
boardHeight = e.getHeight();
repaint();
}
@Override
public void boardCellsUpdate(BoardEvent e) {
// here is where i get the error
// while we are rendering we don't want the cells to render to change
while (rendering){
try {
// we don't want it to sleep to much to keep what we render up to date
// 33 ms is near 1/30 s then we can say we skip a frame (that's false as we don't redraw on frame change but on board update)
Thread.sleep(33);
// this seems to be called "busy waiting" and to be bad but as i don't know how to do better and this work
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
cells = e.getCellsToRender();
repaint();
}
private int getBoardHeight() {
if(boardHeight == -1){
return cells.last().getY();
}
return boardHeight;
}
private int getBoardWidth() {
if (boardWidth == -1){
return cells.last().getX();
}
return boardWidth;
}
}
Итак, ошибка возникает, когда я изменяю размер окна во время обновления платы. сказать, что я нашел do c об ожидании и уведомлении, но я этого не понимаю, поэтому, если вы хорошо сделаете c о потоке, поделитесь им, я буду очень рад, если смогу узнать больше о потоке. ^^
кто-то попросил минимальный воспроизводимый образец, но поскольку я просто не знаю, как сделать хороший, я отправляю вам свой исходный код он маленький (5 КБ) и есть нет зависимости
Я уже слышал о специальном потоке Swing, я постараюсь узнать немного больше об этом
Я попытался добавить модификатор syncronized
к cells
но моей IDE это не нравится, если я хорошо помню, только методы могут быть syncronized
другое редактирование, чтобы сказать вам, что я нашел способ сделать добавление ошибки очень простым, просто замените
for( AbstractCell c: cells){
cellRenderer.renderCell(c,g);
}
от
for( AbstractCell c: cells){
try {
Thread.sleep(33);
} catch (InterruptedException e) {
e.printStackTrace();
}
cellRenderer.renderCell(c,g);
}
и не забудьте прокомментировать эту часть
// while we are rendering we don't want the cells to render to change
while (rendering){
try {
// we don't want it to sleep to much to keep what we render up to date
// 33 ms is near 1/30 s then we can say we skip a frame (that's false as we don't redraw on frame change but on board update)
Thread.sleep(33);
// this seems to be called "busy waiting" and to be bad but as i don't know how to do better and this work
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}