在多个线程之间同步状态

时间:2019-06-19 14:26:11

标签: java multithreading swing

我有一张桌子和几个机器人(仅适用于现在的2个),它们试图在表格中找到从起点到目标的最短路径。

每个bot是一个线程,该线程将表中已阻止和未阻止的单元格保持在状态。

每个线程都已订阅其他线程。当某个线程执行并移动时,它会向其他线程发送通知,告知它已释放先前占用的单元并阻塞了另一个单元。

看起来像这样

enter image description here

每个线程的主循环看起来像这样

@Override
public void run() {
    // render original position
    notifyObserver(ChangeStateEvent
        .builder()
        .identifier(npc.getIdentifier())
        .newState(
            NPCWalkState.builder()
                .row(startVertex.getRow())
                .column(startVertex.getColumn())
                .build())
        .build());
    while (!startVertex.equals(goalVertex)) {
        ThreadUtils.delaySeconds(speed);

        Vertex nextStep = pathSearch.find(startVertex, goalVertex, cellStates).get(1);

        ChangeStateEvent event = ChangeStateEvent.builder()
            .identifier(npc.getIdentifier())
            .newState(
                NPCWalkState.builder()
                    .row(nextStep.getRow())
                    .column(nextStep.getColumn())
                    .build())
            .previousState(
                NPCWalkState.builder()
                    .row(startVertex.getRow())
                    .column(startVertex.getColumn())
                    .build())
            .build();
        notifyObserver(event);
        startVertex = new Vertex(nextStep);
    }
}

监听器方法如下

@Override
public void receiveNotification(ChangeStateEvent data) {
    if (null != data.getPreviousState()) {
        // freed cells
        int free_row = data.getPreviousState().getRow();
        int free_column = data.getPreviousState().getColumn();
        // blocked cells
        int blocked_row = data.getNewState().getRow();
        int blocked_column = data.getNewState().getColumn();

        cellStates[free_row][free_column] = false;
        cellStates[blocked_row][blocked_column] = true;
    } else {
        // blocked cells
        int blocked_row = data.getNewState().getRow();
        int blocked_column = data.getNewState().getColumn();

        cellStates[blocked_row][blocked_column] = true;
    }
}

cellStates是一个基本的布尔矩阵

private boolean[][] cellStates;

但是有时那些移动的机器人彼此重叠-因此它们同时进入相同的单元格。最后,他们达到了理想的目的地。

但是我想摆脱这种行为。如何实现?

据我了解,我应该阻止搜索,直到cellState消息中的receiveNotification的状态被更新,或者如果搜索开始就阻止更新cellState

我也不排除表本身是造成重叠的原因-因为它也订阅了线程事件

@Override
public void receiveNotification(ChangeStateEvent data) {
    if (null != data.getPreviousState()) {
        int previousRow = data.getPreviousState().getRow();
        int previousColumn = data.getPreviousState().getColumn();
        int currentRow = data.getNewState().getRow();
        int currentColumn = data.getNewState().getColumn();
        SwingUtilities.invokeLater(() -> {
            List<T> oldCellContent = (List<T>) table.getValueAt(previousRow, previousColumn);
            oldCellContent.remove(data.getIdentifier());
            table.setValueAt(oldCellContent, previousRow, previousColumn);

            List<T> newCellContent = (List<T>) table.getValueAt(currentRow, currentColumn);
            newCellContent.add(0, (T) data.getIdentifier()); // on top TODO: player should be prioritized
            table.setValueAt(newCellContent, currentRow, currentColumn);
        });
    } else {
        int currentRow = data.getNewState().getRow();
        int currentColumn = data.getNewState().getColumn();
        SwingUtilities.invokeLater(() -> {
            List<T> newCellContent = (List<T>) table.getValueAt(currentRow, currentColumn);
            newCellContent.add(0, (T) data.getIdentifier());
            table.setValueAt(newCellContent, currentRow, currentColumn);
        });
    }
}

0 个答案:

没有答案