【发布时间】:2016-12-25 14:49:06
【问题描述】:
我有一个作业需要在 Java 中实现数独求解器的顺序和并行版本(使用 ForkJoin 框架进行并行处理)。
我写了顺序的,它工作正常。算法思想是一个简单的回溯练习:对于每个尚未填充的单元格(从表格的左上角开始),用所有合法候选人(从 1 到 9 的整数),直到您到达矩阵的末尾(第 9 行第 9 行)。如果您已到达终点,则增加解决方案编号。
我想实现并行版本,只是为为特定单元格找到的每个有效候选者生成一个新线程,然后等待它们。它似乎不起作用,我无法找到原因。
我发布了应该完成整个工作的课程,希望能找到一个好的建议:
class SolveSudoku extends RecursiveAction{
private int i, j;
private int[][] cells;
SolveSudoku(int i, int j, int[][] cells){
this.i = i;
this.j = j;
this.cells = cells;
}
@Override
protected void compute(){
if (j == 9) {
j = 0;
if (++i == 9){
solutions++;
System.out.println(solutions);
return;
}
}
if (cells[i][j] != 0 ){ // skip filled cells
SolveSudoku s = new SolveSudoku(i, j+1, cells);
s.compute();
return;
}
ArrayList<Integer> vals = new ArrayList<Integer>();
for (int val = 1; val <= 9; val++) // try all the legal candidates for i, j
if (legal(i,j,val,cells))
vals.add(val);
if(vals.size() == 1){ // only one, no new threads
cells[i][j] = vals.get(0);
new SolveSudoku(i, j+1, cells).compute();
}
else{
SolveSudoku threads[] = new SolveSudoku[vals.size()];
int n = 0;
int first;
for(int k=0; k<vals.size(); k++){
if(k == vals.size()-1){
cells[i][j] = vals.get(k);
threads[n] = new SolveSudoku(i, j+1, cells);
threads[n].compute();
}
else{
cells[i][j] = vals.get(k);
threads[n] = new SolveSudoku(i, j+1, cells);
threads[n].fork();
}
n++;
}
for(int k=0; k<threads.length-1; k++)
if(k != vals.size()-1)
threads[k].join();
}
cells[i][j] = 0;
return;
}}
new ForkJoinPool().invoke(new SolveSudoku(0, 0, M)); // where *M* is a sudoku instance to solve where all the unfilled cells contain '0'
【问题讨论】:
-
那么并行算法应该一次性解决整个数独问题?
-
是的,@vatbub!事实上,如果你定义了一个经典的 main 方法(在类定义之外的行),并且如果你在下面添加行 threads[n].join(); else 块的最后一行(在 for 循环中),一切正常。不知道错误在哪里,但似乎线程做了他们想做的事......
标签: java parallel-processing sudoku fork-join forkjoinpool