当数据在其他线程中发生变化时实现多线程

时间:2016-04-28 14:06:20

标签: java multithreading sudoku

我有一个单线程数独求解器,我想使用多线程。我计划将N个线程委托给板上的每个阵列。每个线程将返回他们在每个单元格中找到的可能性的数量,并从那里我们测试这些值并在必要时回溯。

我坚持的是一旦线程在板上插入一个可能的值,如何保持一致,因为它改变了其他线程中的可能性。

我正在使用一种名为最受约束的变量的启发式算法。在每个步骤中,我们计算每个单元格中的可能性数量,并尝试在该单元格中找到具有最小可能的候选项以最小化冲突的值。例如:

 1 2  0 0
 0 0  0 0

 0 0  0 0
 0 0  3 4

第1行第3列具有最少的候选者(1),并且只有4个可以放在那里。这是算法的核心,也是我想要使用多线程并行化的内容。

这是我用来解决数独谜题的课程:

public class LogicalSolver
{
    private int numberOfSteps;
    public LogicalSolver()
    {
        numberOfSteps = 0;
    }
    public boolean runLogicSolver(SudokuBoard board)
    {
        return logicalSolver(board);
    }
    private boolean logicalSolver(SudokuBoard board)
    {
        boolean solved = false;
        int row = -1;
        int column = -1;
        int candidates[] = new int[board.GRIDSIZE];
        int numOfCandidates = 0;
        for (int currentRow = 0; currentRow < board.GRIDSIZE; currentRow++)
        {
            for (int currentColumn = 0; currentColumn < board.GRIDSIZE; currentColumn++)
            {
                if (board.getValue(currentRow, currentColumn) == 0)
                {
                    int newCandidates[] = getCandidates(board, currentRow, currentColumn);
                    int numOfNewCandidates = getNumOfNewCandidates(newCandidates);
                    if (row < 0 || numOfNewCandidates < numOfCandidates)
                    {
                        row = currentRow;
                        column = currentColumn;
                        candidates = newCandidates;
                        numOfCandidates = numOfNewCandidates;
                    }
                }
            }
        }
        if (row < 0)
        {
            solved = true;
        }
        else
        {
            for (int i = 0; i < candidates.length && candidates[i] != 0; i++)
            {
                board.setValue(row, column, candidates[i]);
                numberOfSteps++;
                if (logicalSolver(board))
                {
                    solved = true;
                    break;
                }
                board.setValue(row, column, 0);
            }
        }
        return solved;
    }
    private int[] getCandidates(SudokuBoard board, int row, int column)
    {
        int newCandidates[] = new int[board.GRIDSIZE];
        int index = 0;
        for (int value = 1; value <= board.GRIDSIZE; value++)
        {
            boolean collision = false;
            for (int offset = 0; offset < board.GRIDSIZE; offset++)
            {
                int rowSubGrid = (row - row % board.ROWS) + (offset / board.ROWS);
                int columnSubGrid = (column - column % board.COLUMNS) + (offset % board.COLUMNS);
                if (board.getValue(row, offset) == value || board.getValue(offset, column) == value
                   || board.getValue(rowSubGrid, columnSubGrid) == value)
                {
                    collision = true;
                    break;
                }
            }
            if (!collision)
            {
                newCandidates[index] = value;
                index++;
            }
        }
        return newCandidates;
    }
    private int getNumOfNewCandidates(int newCandidates[])
    {
        int numOfNewCandidates = 0;
        for (int i = 0; i < newCandidates.length && newCandidates[i] != 0; i++)
        {
            numOfNewCandidates++;
        }
        return numOfNewCandidates;
    }
    public void displayNumberOfSteps()
    {
        System.out.println("It took " + numberOfSteps + " steps to solve this puzzle. \n");
    }
}

1 个答案:

答案 0 :(得分:0)

我认为这是使用ForkJoinTask和ForkJoinPool的绝佳场所。

在前往解决方案的每一步中,您都会创建一个新的ForkJoinTask来探索每个可能的下一步。

每个任务都有自己正在研究的状态的副本,因此在设置单元格时无需同步。而是设置单元格会产生一个新的ForkJoinTask来探索设置该单元格的后果。

如果你必须同步,那么你将失去多线程的一些好处。