Java 多线程的非确定性行为
Posted
技术标签:
【中文标题】Java 多线程的非确定性行为【英文标题】:Non-deterministic behavior with Java Multithreading 【发布时间】:2021-11-12 22:51:02 【问题描述】:我编写了一个简单的程序,用于在 Java 中练习多线程。目标是测试数独解决方案是否有效:行、列或子网格中没有重复的数字。在这一点上,我不在乎条目必须来自 1-9。当数独解法无效时,程序运行良好。当数独解决方案有效时(在同一输入上),程序仅在某些时候有效。具体来说,“win”可能会被打印出来,也可能不会被打印出来。
我的程序通过创建 RowThread、ColumnThread 和 GridThread 来工作。他们每个人都分别检查解决方案是否具有有效的行、列和网格。当一个线程完成检查后,它会调用 SudokuTest 中适当的 setter 方法,如果解决方案无效,它将调用 Main 中的 end 方法。如果线程没有判断出解决方案无效,setter方法会记录行、列或网格已经被检查过,然后调用allChecked方法。 allChecked 检查是否已检查行、列和网格。如果是这样,那么解决方案是有效的,所以它调用 Main.success(),它应该打印“win”。这是我的主要课程:
public class Main
public static void end()//called by SudokuTest when the solution is invalid
System.out.println("fail");
System.exit(0);
public static void success() //called by SudokuTest when the solution is valid
System.out.println("win");/*this line will not always print,
but it is reached in the debugger when I set a breakpoint.*/
System.exit(0);
public static void main(String[] args)
int[][] sudokuSolution = new int[9][9];
int k = 0;
for (int i = 0; i < 9; i++) //loop fills up a 2d array with the numbers 0-80, a valid solution
for (int j = 0; j < 9; j++)
sudokuSolution[i][j] = k;
k++;
//sudokuSolution[1][1] = 0;//Testing an invalid solution
SudokuTest t = new SudokuTest();//
Runnable r = new RowThread(sudokuSolution, t);
Runnable c = new ColumnThread(sudokuSolution, t);
Runnable g = new GridThread(sudokuSolution, t);
new Thread(r).start();
new Thread(c).start();
new Thread(g).start();
我的 RowThread 类:
public class RowThread implements Runnable
int[][] _sudoku;
SudokuTest _t;
public RowThread(int[][] sudoku, SudokuTest t)
_sudoku = sudoku;
_t = t;
private void isFail() //issue: how to get this info back to my Main function?
for(int i = 0; i < _sudoku.length; i++)
for(int j = 0; j< _sudoku.length; j++)
for (int k = j+1; k< _sudoku.length; k++)
if (_sudoku[i][j] == _sudoku[i][k])
_t.setRow(true);
return;
_t.setRow(false);
@Override
public void run()
isFail();
我的 ColumnThread 和 GridThread 类与 RowThread 相同,除了 isFail() 方法中的逻辑。 我的数独测试课:
public class SudokuTest
public boolean _rowBad;
public boolean _colBad;
public boolean _gridBad;
public boolean _rowChecked;
public boolean _colChecked;
public boolean _gridChecked;
public SudokuTest()
public void setRow(boolean b)
_rowBad = b;
_rowChecked = true;
if (b)
Main.end();
public void setCol(boolean b)
_colBad = b;
_colChecked = true;
if (b)
Main.end();
public void setGrid(boolean b)
_gridBad = b;
_gridChecked = true;
if (b)
Main.end();
allChecked();
public void allChecked()
if (_gridChecked && _colChecked && _rowChecked)
Main.success();
【问题讨论】:
你为什么只在setGrid
上打电话给allChecked
?如果最后没有调用它会发生什么?使用等待 latch 的主线程怎么样?只有当所有三个线程都调用成功时才会继续?
我不敢相信我错过了。我的程序现在工作正常。非常感谢!
@PhillipFeldman 请张贴并接受对您自己的问题的回答,以显示解决方案,为后代着想。
【参考方案1】:
答案:正如 Maarten Bodewes 指出的那样,我的错误是没有在 setCol 和 setRow 中调用 allChecked。
【讨论】:
以上是关于Java 多线程的非确定性行为的主要内容,如果未能解决你的问题,请参考以下文章