Как правильно использовать функцию ожидания и уведомления? - PullRequest
0 голосов
/ 07 мая 2020

При кодировании я сталкиваюсь с ошибкой 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();
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...