0

I wrote a simple program that I am using to practice multithreading in Java. The goal is to test whether or not a Sudoku solution is valid: No repeating numbers in rows, columns, or sub-grids. At this point I don't care that the entries must be from 1-9. The program works fine when the Sudoku solution is invalid. When the Sudoku solution is valid (on the same input), the program works only sometimes. Specifically, "win" may or may not be printed.

My program works by creating RowThread, ColumnThread, and GridThread. Each are of them check whether the solution has valid rows, columns and grids, respectively. When a thread is finished checking, it calls the appropriate setter method in SudokuTest, which will call the end method in Main if the solution is invalid. If the thread does not determine that the solution is invalid, the setter method will record that the row, column, or grid has been checked, and then call the allChecked method. allChecked checks if row, column, and grid have been checked. If so, then the solution is valid, so it calls Main.success(), which should print "win." Here is my Main class:

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();

    }
}

My RowThread class:


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();
    }
}

My ColumnThread and GridThread classes are the same as RowThread, except for the logic in the isFail() method. My SudokuTest class:

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();
        }
    }
}

  • 2
    Why do you call `allChecked` only on `setGrid`? What happens if it is not called last? What about using main thread that waits on a **latch** that only continues when all three threads have called success? – Maarten Bodewes Nov 12 '21 at 22:59
  • I can't believe I missed that. My program works fine now. Thankyou so much! – Phillip Feldman Nov 12 '21 at 23:02
  • @PhillipFeldman Please post and accept an Answer to your own Question showing the solution, for the sake of posterity. – Basil Bourque Nov 12 '21 at 23:08

1 Answers1

0

Answer: as Maarten Bodewes pointed out, my mistake was to not call allChecked in setCol and setRow.