#java #multithreading #undefined-behavior #sudoku #non-deterministic
Вопрос:
Я написал простую программу, которую использую для практики многопоточности на Java. Цель состоит в том, чтобы проверить, является ли решение судоку верным: никаких повторяющихся чисел в строках, столбцах или подсетях. На данный момент мне все равно, что записи должны быть от 1 до 9. Программа отлично работает, когда решение судоку неверно. Когда решение судоку действительно (на том же входе), программа работает только иногда. В частности, «победа» может быть напечатана, а может и не быть напечатана.
Моя программа работает, создавая поток строк, поток столбцов и поток сетки. Каждый из них проверяет, имеет ли решение допустимые строки, столбцы и сетки соответственно. Когда поток завершает проверку, он вызывает соответствующий метод настройки в SudokuTest, который вызовет метод end в Main, если решение неверно. Если поток не определит, что решение неверно, метод установщика запишет, что строка, столбец или сетка были проверены, а затем вызовет метод allChecked. Все проверено проверяет, были ли проверены строка, столбец и сетка. Если это так, то решение действительно, поэтому оно вызывает Main.success(), который должен вывести «победа». Вот мой основной урок:
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 lt; 9; i ) { //loop fills up a 2d array with the numbers 0-80, a valid solution for (int j = 0; j lt; 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 lt; _sudoku.length; i ) { for(int j = 0; jlt; _sudoku.length; j ) { for (int k = j 1; klt; _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 amp;amp; _colChecked amp;amp; _rowChecked) { Main.success(); } } }
Комментарии:
1. Почему вы звоните
allChecked
только поsetGrid
телефону ? Что произойдет, если он не будет назван последним? Как насчет использования основного потока, который ожидает защелки , которая продолжается только тогда, когда все три потока вызвали успех?2. Не могу поверить, что я это пропустил. Теперь моя программа работает нормально. Большое Вам спасибо!
3. @PhillipFeldman Пожалуйста, опубликуйте и примите ответ на свой собственный вопрос, показывающий решение, ради потомков.
Ответ №1:
Ответ: как указал Мартен Бодевес, моей ошибкой было не вызывать allChecked в setCol и setRow.