I have a 2D array that represents Game of Life board. N threads work on their own part of the array, creating the next generation.
When all N locks are done with their part, I print the current generation and sleep some time before going to the next generation. It is achieved by using CyclicBarrier.
Although the program works, I think the printing thread might see stale array cells because writes to the array are not synchronized. Internally CyclicBarrier uses lock, so it might trigger happens-before, but I'm not sure about it.
The only solution I see is to lock on Board methods. But I don't want to use locks because each thread has its own dedicated part of the array and it would create unnecessary contention on the lock.
public class GameOfLife {
private final Worker[] workers;
private final long duration;
private final AtomicBoolean done;
private Board current;
public GameOfLife(Board initialBoard, long duration) throws InterruptedException {
initialBoard.print();
this.current = new Board(initialBoard);
this.duration = duration;
this.done = new AtomicBoolean(false);
int cores = Runtime.getRuntime().availableProcessors();
this.workers = new Worker[cores];
CyclicBarrier barrier = new CyclicBarrier(cores, () -> {
current.print();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
GameOfLife.this.done.set(true);
return;
}
Board oldBoard = current;
current = new Board(current);
for (Worker worker : this.workers) {
worker.setOldBoard(oldBoard);
worker.setNewBoard(current);
}
});
int partitionSize = (initialBoard.getRows() / cores) + 1;
for (int core = 0; core < cores; core++) {
workers[core] = new Worker(barrier, initialBoard, current, done, core * partitionSize, Math.min(initialBoard.getRows(), (core + 1) * partitionSize));
}
}
public void start() {
for (Worker worker : this.workers) {
new Thread(worker).start();
}
new Timer(true).schedule(new TimerTask() {
#Override
public void run() {
GameOfLife.this.done.set(true);
}
}, this.duration);
}
public static void main(String[] args) throws InterruptedException {
boolean[][] initialBoard = new boolean[27][27];
for (int row = 10; row < 20; row++) {
initialBoard[row][15] = true;
}
GameOfLife e = new GameOfLife(new Board(initialBoard), 40000);
e.start();
}
}
class Worker implements Runnable {
private final CyclicBarrier barrier;
private final AtomicBoolean done;
private volatile Board oldBoard;
private volatile Board newBoard;
private final int rowStart;
private final int rowEnd;
public Worker(CyclicBarrier barrier, Board oldBoard, Board newBoard, AtomicBoolean done, int rowStart, int rowEnd) {
this.oldBoard = oldBoard;
this.newBoard = newBoard;
this.done = done;
this.rowStart = rowStart;
this.rowEnd = rowEnd;
this.barrier = barrier;
}
#Override
public void run() {
while (!done.get()) {
for (int row = rowStart; row < rowEnd; row++) {
for (int col = 0; col < this.oldBoard.getCols(); col++) {
int neighbors = this.oldBoard.countNeighbors(row, col);
if (this.oldBoard.isAlive(row, col)) {
if (neighbors < 2 || neighbors > 3) {
this.newBoard.kill(row, col);
}
} else {
if (neighbors == 3) {
this.newBoard.create(row, col);
}
}
}
}
try {
barrier.await();
} catch (Exception e) {
System.out.println(e);
return;
}
}
}
public void setOldBoard(Board oldBoard) {
this.oldBoard = oldBoard;
}
public void setNewBoard(Board newBoard) {
this.newBoard = newBoard;
}
}
class Board {
private final boolean[][] board;
Board(Board another) {
this(another.board);
}
Board(boolean[][] aBoard) {
this.board = new boolean[aBoard.length][aBoard[0].length];
for (int row = 0; row < aBoard.length; row++) {
this.board[row] = Arrays.copyOf(aBoard[row], aBoard[row].length);
}
}
public int countNeighbors(int row, int col) {
int counter = 0;
int[][] possibleNeighbors = {{row - 1, col - 1}, {row, col - 1}, {row + 1, col - 1}, {row - 1, col},
{row + 1, col}, {row - 1, col + 1}, {row, col + 1}, {row + 1, col + 1}};
for (int[] possibleNeighbor : possibleNeighbors) {
final int r = possibleNeighbor[0];
final int c = possibleNeighbor[1];
if (insideBoard(r, c) && this.board[r][c]) {
counter++;
}
}
return counter;
}
private boolean insideBoard(int row, int col) {
return row >= 0 && row < this.board.length && col >= 0 && col < this.board[row].length;
}
public int getRows() {
return this.board.length;
}
public int getCols() {
return this.board[0].length;
}
public boolean isAlive(int row, int col) {
return this.board[row][col];
}
public void kill(int row, int col) {
this.board[row][col] = false;
}
public void create(int row, int col) {
this.board[row][col] = true;
}
public void print() {
for (int row = 0; row < this.board.length; row++) {
for (int col = 0; col < this.board[row].length; col++) {
System.out.print(this.board[row][col] ? "*" : " ");
}
System.out.println();
}
}
}
Related
I am trying to solve the N Queen problem using multiple threads. However, the single threaded version of it runs either faster or roughly the same as the multithreaded one.
In essence, I use a queue which all the threads share. They pop states from the queue and expand them and add then them to the queue. I have tried playing around with the number of threads but to no avail, the more threads I add after around 8 the performance degenerates. The algorithm is correct in that the output is the same in both versions.
Any ideas?
Here's the code:
public class Queens {
//Thread
static class Runner implements Runnable {
private BlockingQueue<Configuration> queue;
private final AtomicInteger total;
public Runner(BlockingQueue<Configuration> q, AtomicInteger total) {
this.queue = q;
this.total = total;
}
public void run() {
while(!queue.isEmpty()) {
Configuration currentConfiguration = null;
try {
currentConfiguration = queue.take();
}
catch(InterruptedException e) {
}
if(currentConfiguration.done()) {
//currentConfiguration.printConfiguration();
total.incrementAndGet();
System.out.println("Solution");
continue;
}
for(int i = 0; i < currentConfiguration.getSize(); i++) {
if(safe(currentConfiguration, i, currentConfiguration.getColumn())) {
Configuration childConfig = new Configuration(currentConfiguration.getColumn() + 1,
currentConfiguration.getBoard());
childConfig.place(i, currentConfiguration.getColumn());
queue.add(childConfig);
}
}
}
}
//Returns true if we can place a queen on that row and column.
private boolean safe(Configuration current, int row, int col) {
for (int i = 0; i < col; i++)
if (current.getBoard()[row][i] == 1)
return false;
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--)
if (current.getBoard()[i][j] == 1)
return false;
for (int i = row, j = col; j >= 0 && i < current.getSize(); i++, j--)
if (current.getBoard()[i][j] == 1)
return false;
return true;
}
}
//Board configuration class.
static class Configuration {
private int column;
private int[][] board;
private int size;
public Configuration(int column, int[][] b) {
this.column = column;
this.board = new int[b.length][b.length];
this.size = b.length;
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
board[i][j] = b[i][j];
}
}
}
public int getSize() {
return size;
}
public int getColumn() {
return column;
}
public int[][] getBoard() {
return board;
}
public boolean done() {
if(column == size)
return true;
return false;
}
public void place(int row, int column) {
board[row][column] = 1;
}
//Method prints the current configuration.
public synchronized void printConfiguration() {
synchronized(Configuration.class) {
System.out.println(Thread.currentThread().getName());
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Configuration x = new Configuration(0, new int[13][13]);
int threads = 10;
AtomicInteger totalSolutions = new AtomicInteger(0);
List<Thread> mythreads = new ArrayList<Thread>();
BlockingQueue<Configuration> q = new LinkedBlockingDeque<>();
//Initially the board is empty
q.put(x);
long startTime = System.currentTimeMillis();
//Run 10 threads
for(int i = 0; i < threads; i++) {
Thread newthread = new Thread(new Runner(q, totalSolutions));
newthread.start();
mythreads.add(newthread);
}
for(Thread t : mythreads) {
try {
t.join();
}
catch(Exception e) {};
}
System.out.println(totalSolutions.get());
long endTime = System.currentTimeMillis();
System.out.println("Time: " + (endTime - startTime));
}
}
This was too long for a comment so I have to write it as an answer, apology on that.
In run method I've added the following like:
System.out.println(Thread.currentThread().getName() + " taking " + currentConfiguration.toString() + " out of " + queue.size() + " elem");
When running a single thread program it looks like this:
Thread-0 taking jobs.DeleteMe$Configuration#279b9032 out of 925326 elem
Thread-0 taking jobs.DeleteMe$Configuration#15ced747 out of 925327 elem
Thread-0 taking jobs.DeleteMe$Configuration#42689f59 out of 925328 elem
Thread-0 taking jobs.DeleteMe$Configuration#29aeeda2 out of 925329 elem
When running 10 threads the log looks like:
Thread-6 taking jobs.DeleteMe$Configuration#2775c7e7 out of 39393 elem
Thread-7 taking jobs.DeleteMe$Configuration#4e0ae08b out of 39308 elem
Thread-6 taking jobs.DeleteMe$Configuration#5eb0ba9 out of 39404 elem
Thread-9 taking jobs.DeleteMe$Configuration#12321211 out of 39401 elem
Thread-0 taking jobs.DeleteMe$Configuration#13a07923 out of 39383 elem
Thread-9 taking jobs.DeleteMe$Configuration#442cf86a out of 39415 elem
Thread-0 taking jobs.DeleteMe$Configuration#49366e2a out of 39420 elem
Thread-8 taking jobs.DeleteMe$Configuration#1c4bcfa5 out of 39378 elem
So it seems there is nothing preventing multiple threads to work.
Since your code uses one resource intensively, which is memory.
So I guess the reason is that memory cache is used more efficiently when there is a single thread running instead of multiple threads. It means that single thread access usually Configuration which is already in CPU cache, while when running multithreaded there are more misses.
See:
Is multi-thread memory access faster than single threaded memory access?
On the sidenote, it would probably be efficient to take a configuration which was the most recently added, BlockingQueue takes the first configuration, it would probably be more efficient to use LinkedBlockingDeque.
So I tried with LinkedBlockingDeque, with 10 threads, it runs for
Time: 3753
with 1 thread:
Time: 3352
(it's 3x speedup for me than the version with LinkedBlockingQueue).
Source:
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* #author mladen
*/
public class DeleteMe {
//Thread
static class Runner implements Runnable {
private LinkedBlockingDeque<Configuration> queue;
private final AtomicInteger total;
public Runner(LinkedBlockingDeque<Configuration> q, AtomicInteger total) {
this.queue = q;
this.total = total;
}
public void run() {
while (!queue.isEmpty()) {
Configuration currentConfiguration = null;
//try {
currentConfiguration = queue.removeLast();
//System.out.println(Thread.currentThread().getName() + " taking " + currentConfiguration.toString() + " out of " + queue.size() + " elem");
// } catch (InterruptedException e) {
//
// }
if (currentConfiguration.done()) {
//currentConfiguration.printConfiguration();
total.incrementAndGet();
System.out.println("Solution");
continue;
}
for (int i = 0; i < currentConfiguration.getSize(); i++) {
if (safe(currentConfiguration, i, currentConfiguration.getColumn())) {
Configuration childConfig = new Configuration(currentConfiguration.getColumn() + 1,
currentConfiguration.getBoard());
childConfig.place(i, currentConfiguration.getColumn());
queue.add(childConfig);
}
}
}
}
//Returns true if we can place a queen on that row and column.
private boolean safe(Configuration current, int row, int col) {
for (int i = 0; i < col; i++) {
if (current.getBoard()[row][i] == 1) {
return false;
}
}
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (current.getBoard()[i][j] == 1) {
return false;
}
}
for (int i = row, j = col; j >= 0 && i < current.getSize(); i++, j--) {
if (current.getBoard()[i][j] == 1) {
return false;
}
}
return true;
}
}
//Board configuration class.
static class Configuration {
private int column;
private int[][] board;
private int size;
public Configuration(int column, int[][] b) {
this.column = column;
this.board = new int[b.length][b.length];
this.size = b.length;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = b[i][j];
}
}
}
public int getSize() {
return size;
}
public int getColumn() {
return column;
}
public int[][] getBoard() {
return board;
}
public boolean done() {
if (column == size) {
return true;
}
return false;
}
public void place(int row, int column) {
board[row][column] = 1;
}
//Method prints the current configuration.
public synchronized void printConfiguration() {
synchronized (Configuration.class) {
System.out.println(Thread.currentThread().getName());
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Configuration x = new Configuration(0, new int[13][13]);
int threads = 1;
AtomicInteger totalSolutions = new AtomicInteger(0);
List<Thread> mythreads = new ArrayList<Thread>();
LinkedBlockingDeque<Configuration> q = new LinkedBlockingDeque<>();
//Initially the board is empty
q.put(x);
long startTime = System.currentTimeMillis();
//Run 10 threads
for (int i = 0; i < threads; i++) {
Thread newthread = new Thread(new Runner(q, totalSolutions));
newthread.start();
mythreads.add(newthread);
}
for (Thread t : mythreads) {
try {
t.join();
} catch (Exception e) {
};
}
System.out.println(totalSolutions.get());
long endTime = System.currentTimeMillis();
System.out.println("Time: " + (endTime - startTime));
}
}
The synchronization overhead is massive here. Try doing more work without fetching from the queue all the time.
Also, between the isEmpty call and the take call the queue can become empty. Avoid this race condition by using poll and checking for null result.
The memory overhead can be mitigated by going depth-first instead of breadth-first.
Code follows:
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class Queens {
//Thread
static class Runner implements Runnable {
private BlockingQueue<Configuration> queue;
private final AtomicInteger total;
private boolean local;
public Runner(BlockingQueue<Configuration> q, AtomicInteger total) {
this.queue = q;
this.total = total;
}
public void run() {
while(true) {
Configuration currentConfiguration = null;
try {
currentConfiguration = queue.poll(50, TimeUnit.MILLISECONDS);
}
catch(InterruptedException e) {
}
if(!local && queue.size() > 1000) local = true;
if(currentConfiguration == null){
break;
}
recurse(currentConfiguration);
}
System.out.println("DONE");
}
public void recurse(Configuration c){
if(c.done()){
total.incrementAndGet();
return;
}
for(int i = 0; i < c.getSize(); i++) {
if(safe(c, i, c.getColumn())) {
c.place(i, c.getColumn());
c.setColumn(c.getColumn() + 1);
if(local){
recurse(c);
}else{
queue.add(c.clone());
}
c.setColumn(c.getColumn() - 1);
c.clear(i, c.getColumn());
}
}
}
//Returns true if we can place a queen on that row and column.
private boolean safe(Configuration current, int row, int col) {
for (int i = 0; i < col; i++)
if (current.getBoard()[row][i] == 1)
return false;
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--)
if (current.getBoard()[i][j] == 1)
return false;
for (int i = row, j = col; j >= 0 && i < current.getSize(); i++, j--)
if (current.getBoard()[i][j] == 1)
return false;
return true;
}
}
//Board configuration class.
static class Configuration {
private int column;
private int[][] board;
private int size;
public Configuration(int column, int[][] b) {
this.column = column;
this.board = new int[b.length][b.length];
this.size = b.length;
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
board[i][j] = b[i][j];
}
}
}
public Configuration clone(){
return new Configuration(column, board);
}
public int getSize() {
return size;
}
public int getColumn() {
return column;
}
public void setColumn( int v) {
column = v;
}
public int[][] getBoard() {
return board;
}
public boolean done() {
if(column == size)
return true;
return false;
}
public void place(int row, int column) {
board[row][column] = 1;
}
public void clear(int row, int column){
board[row][column] = 0;
}
//Method prints the current configuration.
public synchronized void printConfiguration() {
synchronized(Configuration.class) {
System.out.println(Thread.currentThread().getName());
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
final int size = 14;
Configuration x = new Configuration(0, new int[size][size]);
int threads = 8;
AtomicInteger totalSolutions = new AtomicInteger(0);
List<Thread> mythreads = new ArrayList<Thread>();
BlockingQueue<Configuration> q = new LinkedBlockingDeque<>();
//Initially the board is empty
q.put(x);
long startTime = System.currentTimeMillis();
//Run 10 threads
for(int i = 0; i < threads; i++) {
Thread newthread = new Thread(new Runner(q, totalSolutions));
newthread.start();
mythreads.add(newthread);
}
for(Thread t : mythreads) {
try {
t.join();
}
catch(Exception e) {};
}
System.out.println(totalSolutions.get());
long endTime = System.currentTimeMillis();
System.out.println("Time: " + (endTime - startTime));
}
}
How can I make the second iteration use the first array "poqet" to switch their positions from true to false, but without changing their state when the first iteration made them all true?
public class Dhoma {
public static void main(String[] args) {
boolean poqet[] = new boolean[100];
int njerezit[] = new int[100];
int count = 0;
int nrRendorP = 0;
int nrRendorN = 0;
for (int i = 0; i < njerezit.length; i++) {
nrRendorN++;
for (int k = 0; k < poqet.length; k++) {
nrRendorP++;
if (nrRendorP == 100) {
nrRendorP = 0;
}
poqet[i] = Switch(nrRendorN, nrRendorP);
System.out.println(k + " " + poqet[i]);
}
}
// System.out.println("Jane te ndezura "+ count);
}
private static boolean Switch(int nr, int n) {
if (n % nr == 0) {
return true;
}
return false;
}
}
I'm trying to create a Sudoku solver in Java, in general I'm new to programming and to Java. I don't really know how to handle this kind of errors.
I keep getting a stack overflow error.
I tried diffrent codes for it , none of them worked but anyways here is my latest one:
public class Sudoku {
private int[][] values;
private boolean [][] writable;
private static final int ZERO = 0;
private static final int SIZE = 9;
//just a normal constructor that sets which values are changeable and which aren't. only values equal to zero are changeable.
public Sudoku(int[][] values) {
this.values = new int[SIZE][SIZE];
for(int row = 0; row< SIZE ; row++)
{
for(int col = 0; col< SIZE; col++)
{
this.values[row][col] = values[row][col];
}
}
writable = new boolean[values.length][values[1].length];
for(int i = 0;i < writable.length;i++)
{
for(int j = 0; j<writable[1].length;j++)
{
if(values[i][j] == ZERO)
{
writable[i][j] = true;
}
}
}
}
public void setValues(int row,int col ,int value) //changes the value if the value was changeable.
{
if(writable[row][col])
{
values[row][col]= value;
}
}
public int getValue(int row,int col) {
return values[row][col];
}
public boolean isWritable(int row,int col)
{
return writable[row][col];
}
private boolean ConflictAtRow(int row , int num)
{
for(int i = 0;i < SIZE;i++)
if(getValue(row,i) == num)
return true;
return false;
}
private boolean ConflictAtCol(int col, int num)
{
for(int i = 0;i<SIZE;i++)
if(getValue(i,col) == num)
return true;
return false;
}
private boolean ConflictAtBox(int row, int col, int num)
{
int r = row - row %3;
int c = col - col %3;
for(int i = r;i<r+3;i++)
{
for(int j = c;j<c+3;j++)
{
if(getValue(i, j) == num && row != i && col != j)
return true;
}
}
return false;
}
private boolean ConflictAt(int row, int col, int num)
{
return ConflictAtBox(row, col, num) && ConflictAtCol(col,num) && ConflictAtRow(row, num); //line 108
}
public boolean solve(int row,int col)
{
int nextRow = (col < 8) ? row:row+1;
int nextCol = (col +1)%9;
for (row = nextRow; row < SIZE; row++) {
for (col = NextCol; col < SIZE; col++) {
if(isWritable(row,col))
{
for (int num = 1; num <= 9; num++) {
if(!ConflictAt(row,col,num)) //line 118
{
setValues(row,col,num);
if(solve(nextRow,nextCol)) //line 122
return true;
}
setValues(row,col,ZERO);
}
}return !ConflictAt(row,col,getValue(row,col)) &&
solve(nextRow,nextCol);;
}
}return true;
}
and when I run the solve() method I get the stack overflow error
Exception in thread "main" java.lang.StackOverflowError
at Sudoku.Sudoku.ConflictAt(Sudoku.java:108)
at Sudoku.Sudoku.solve(Sudoku.java:118)
at Sudoku.Sudoku.solve(Sudoku.java:122)
at Sudoku.Sudoku.solve(Sudoku.java:122)
at Sudoku.Sudoku.solve(Sudoku.java:122)
at Sudoku.Sudoku.solve(Sudoku.java:122)
and so on ......
Once the control enters the solve() method for the first time, and if all the if conditions evaluate to true up to line 122, you are calling the solve() method again.
The problem is, every time the control hits this method, it is as though it were executing it for the first time. Because there is no change in conditions (for loops always start at 0).
What this means is, the solve() method gets repeatedly called until the stack runs out of memory.
I've a problem with an exercise. I need to find all the solutions for a given sudoku, using fork/join parallelism. I made an algorithm but it seems it doesn't work. It stops at some point and I can't figure it out why.
Here's the code:
private static int counter;
private Cella[][] sudoku;
private int i;
private int j;
private int theCounter = 0;
public SudokuMulti(Cella[][] sudoku) {
this.sudoku = sudoku;
}
public SudokuMulti(Cella[][] sudoku, int i, int j) {
this.sudoku = sudoku;
this.i = i;
this.j = j;
}
//DELETED
// Copy the sudoku matrix
private Cella[][] createCopy() {
Cella[][] toReturn = new Cella[9][9];
for (int i = 0; i < 9; i++) {
System.arraycopy(sudoku[i], 0, toReturn[i], 0, 9);
}
return toReturn;
}
And the code for the object Cella:
public class Cella {
private int current;
public Cella() {
current = 0;
}
public Cella(int current) {
this.current = current;
}
//Getter and Setter
My idea is to give to each thread the faculty to solve its own sudoku, given the "legal values" of the candidate cell. I then collect all threads in an ArrayList and ask them to fork with the last for. Every thread should return an Integer (0 for no success, 1 for success) in order to count how many possible sudokus can be solved.
However, the algorithm only covers 1/3 of the sudoku: after a certain point, it stops filling the cells and it just returns without completing it.
Can someone suggest me where I'm doing mistake(s) ?
From what code you have posted, I cannot see any issue that explains your problem. However, you have not posted code that I can compile and execute myself (known as a Minimum Working or Verifiable Example, see Wikipedia and StackOverflow's guide on creating one), nor have you posted a stack trace or output for your application. This makes it difficult to help you solve your problem. If you can provide me with more, I am willing to continue helping you with your problem.
In the meantime, I tried to throw together a program that solves the same problem following your approach. It seems to work, though I have not thoroughly unit-tested it. Perhaps you can compare it to what you wrote and use the differences to discover the problem. You will need at least Java 7 to compile and run this code.
If this is for a homework assignment, I recommend checking with your professor or TA before looking at this listing.
public class Main {
public static void main( String[] args ) {
Sudoku puzzle = new Sudoku();
// Uncomment these lines to have a uniquely solvable Sudoku puzzle. They are commented out to prove that this code can count multiple solutions.
// puzzle.set(1, 0, 2);
// puzzle.set(2, 0, 9);
// puzzle.set(4, 0, 5);
// puzzle.set(7, 0, 4);
// puzzle.set(8, 0, 1);
// puzzle.set(3, 1, 8);
// puzzle.set(6, 1, 3);
// puzzle.set(2, 2, 3);
puzzle.set(3, 2, 7);
puzzle.set(4, 2, 4);
puzzle.set(5, 2, 9);
puzzle.set(6, 2, 6);
puzzle.set(3, 3, 4);
puzzle.set(6, 3, 2);
puzzle.set(7, 3, 1);
puzzle.set(1, 4, 6);
puzzle.set(3, 4, 3);
puzzle.set(4, 4, 7);
puzzle.set(5, 4, 1);
puzzle.set(7, 4, 8);
puzzle.set(1, 5, 4);
puzzle.set(2, 5, 1);
puzzle.set(5, 5, 6);
puzzle.set(2, 6, 5);
puzzle.set(3, 6, 9);
puzzle.set(4, 6, 2);
puzzle.set(5, 6, 8);
puzzle.set(6, 6, 7);
puzzle.set(2, 7, 4);
puzzle.set(5, 7, 7);
puzzle.set(0, 8, 3);
puzzle.set(1, 8, 7);
puzzle.set(4, 8, 6);
puzzle.set(6, 8, 5);
puzzle.set(7, 8, 2);
SudokuSolver solver = new SudokuSolver(puzzle);
long start = System.nanoTime();
int totalSolutions = solver.compute();
long end = System.nanoTime();
System.out.println(totalSolutions);
System.out.format("%f ms", (end - start) / 1e6);
}
private static class Sudoku {
private final int[][] cells;
Sudoku() {
cells = new int[9][9];
}
Sudoku( Sudoku original ) {
cells = new int[9][9];
for (int column = 0; column < 9; ++column) {
for (int row = 0; row < 9; ++row) {
set(column, row, original.get(column, row));
}
}
}
int get( int column, int row) {
return cells[column][row];
}
void set( int column, int row, int value ) {
cells[column][row] = value;
}
boolean isPlausible() {
return columnsArePlausible() && rowsArePlausible() && blocksArePlausible();
}
private boolean columnsArePlausible() {
boolean result = true;
for (int column = 0; result && column < 9; ++column) {
result = isColumnPlausible(column);
}
return result;
}
private boolean isColumnPlausible( int column ) {
boolean result = true;
boolean[] seen = new boolean[10];
for (int row = 0; result && row < 9; ++row) {
int value = get(column, row);
if (value > 0 && seen[value]) {
result = false;
} else {
seen[value] = true;
}
}
return result;
}
private boolean rowsArePlausible() {
boolean result = true;
for (int row = 0; result && row < 9; ++row) {
result = isRowPlausible(row);
}
return result;
}
private boolean isRowPlausible( int row ) {
boolean result = true;
boolean[] seen = new boolean[10];
for (int column = 0; result && column < 9; ++column) {
int value = get(column, row);
if (value > 0 && seen[value]) {
result = false;
} else {
seen[value] = true;
}
}
return result;
}
private boolean blocksArePlausible() {
boolean result = true;
for (int column = 0; result && column < 9; column += 3) {
for (int row = 0; result && row < 9; row += 3) {
result = isBlockPlausible(column, row);
}
}
return result;
}
private boolean isBlockPlausible( int column, int row ) {
boolean result = true;
boolean[] seen = new boolean[10];
for (int x = 0; result && x < 3; ++x) {
for (int y = 0; result && y < 3; ++y) {
int value = get(column + x, row + y);
if (value > 0 && seen[value]) {
result = false;
} else {
seen[value] = true;
}
}
}
return result;
}
}
private static class SudokuSolver extends RecursiveTask<Integer> {
private static final long serialVersionUID = 8759452522630056046L;
private Sudoku state;
private int column;
private int row;
SudokuSolver( Sudoku state ) {
this.state = state;
// These settings allow the search loop in compute() to increment first without asking questions about
// whether this cell has been checked yet.
column = -1;
row = 8;
}
SudokuSolver( Sudoku state, int column, int row ) {
this.column = column;
this.row = row;
this.state = state;
}
#Override
protected Integer compute() {
int viableSolutions = 0;
if (state.isPlausible()) {
int originalColumn = column;
int originalRow = row;
do {
if (row + 1 >= 9) {
++column;
row = 0;
} else {
++row;
}
} while (column < 9 && state.get(column, row) != 0);
if (column >= 9) {
viableSolutions = 1;
} else {
List<SudokuSolver> solvers = new ArrayList<>();
for (int value = 1; value <= 9; ++value) {
Sudoku copy = new Sudoku(state);
copy.set(column, row, value);
solvers.add(new SudokuSolver(copy, column, row));
}
invokeAll(solvers);
for (SudokuSolver solver : solvers) {
viableSolutions += solver.join();
}
}
}
return viableSolutions;
}
}
}
Since this code times how long it takes to count the solutions, the output can vary, but I got
354
709.848410 ms
I've found a solution. Here is the error:
// Copy the sudoku matrix
private Cella[][] createCopy() {
Cella[][] toReturn = new Cella[9][9];
for (int i = 0; i < 9; i++) {
// !!ERROR!!
System.arraycopy(sudoku[i], 0, toReturn[i], 0, 9);
}
return toReturn;
}
When I copy the array I fill it with the Cella object reference and not with a new one, so it causes data races.
The correct way to copy the matrix is:
private Cella[][] createCopy() {
Cella[][] toReturn = new Cella[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
toReturn[i][j] = new Cella(sudoku[i][j].getCurrent());
}
}
return toReturn;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have following homework to do:
Implement parallel searching for specified element in array. Use number of threads as a function parameter. Eeach thread checks own array piece size of (ArraySize/NumberOfThreads).
class MyThread extends Thread {
final int[] SEARCH_TAB;
final int RANGE_TAB[][];
final int SEARCH_VALUE;
static int searchIndex = -1;
static boolean isWorking = true;
int whichThread;
MyThread(int[] searchTab, int[][] rangeTab, int searchValue, int whichThread) {
SEARCH_TAB = searchTab;
RANGE_TAB = rangeTab;
SEARCH_VALUE = searchValue;
this.whichThread = whichThread;
}
#Override
public void run() {
for (int i = RANGE_TAB[whichThread][0]; i < RANGE_TAB[whichThread][1] && isWorking; ++i) {
synchronized(this) {
if (SEARCH_TAB[i] == SEARCH_VALUE) {
isWorking = false;
searchIndex = i;
}
}
}
}
}
class Main {
private static int[][] range(int n, int p) {
int[] quantities = new int[p];
int remainder = n % p;
int quotient = n/p;
int i;
for (i = 0; i < p; ++i) quantities[i] = quotient;
i = 0;
while (remainder != 0) {
--remainder;
++quantities[i];
++i;
}
int[][] tab = new int[p][2];
tab[0][0] = 0;
tab[0][1] = quantities[0];
for (i = 1; i < p; ++i) {
tab[i][0] = tab[i-1][1];
tab[i][1] = tab[i][0] + quantities[i];
}
return tab;
}
private static int search(int[] searchTab, int numberOfThreads, int searchValue) {
int[][] rangeTab = range(searchTab.length, numberOfThreads);
Thread[] threads = new Thread[numberOfThreads];
for ( int i = 0; i < numberOfThreads; ++i) threads[i] = new MyThread(searchTab, rangeTab, searchValue, i);
for ( int i = 0; i < numberOfThreads; ++i) threads[i].start();
return MyThread.searchIndex;
}
public static void main(String[] args) {
int[] tab = {0, 1, 2, 3, 4, 5, 6, 7 , 8, 9, 10};
int value = 5;
int valueIndex = search(tab, 1, value);
if (valueIndex == -1) System.out.println("Not found.");
else System.out.println(valueIndex);
}
}
This code generally works but cant't find index when one thread is implemented. By the way my teacher said that my code is too long and complicated any suggestions with that?
I will be grateful for any kind of help.
How about the following code:
public class Searcher implements Runnable {
private int intToFind;
private int startIndex;
private int endIndex;
private int[] arrayToSearchIn;
public Searcher(int x, int s, int e, int[] a) {
intToFind = x;
startIndex = s;
endIndex = e;
arrayToSearchIn = a;
}
public void run() {
for (int i = startIndex; i <= endIndex; i++) {
if (arrayToSearchIn[i] == intToFind) System.out.println("Found x at index: " + i);
}
}
}
public class Starter {
public static void main(String[] args) {
int[] a = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int numberOfThreads = 5;
int x = 20;
findElement(numberOfThreads, x, a);
}
private static void findElement(int numberOfThreads, int x, int[] a) {
int sizeOfa = a.length;
int range = sizeOfa/numberOfThreads;
for (int i = 0; i <= numberOfThreads-1; i++) {
Thread searcher;
if (i == numberOfThreads-1) {
searcher = new Thread(new Searcher(x, i*range, sizeOfa-1, a));
} else {
searcher = new Thread(new Searcher(x, i*range, i*range+range-1, a));
}
searcher.start();
}
}
}
You can still optimize the code e.g. by splitting the rest of the array on all threads instead of just pushing it into the last one (like in my code) but the idea is still the same.
EDIT: I think that there is a problem with your code. It will only show one appearance of x in the array. If you are looking for x = 5 in [5,5,5,5,5] using five threads you can neven know which index will be returned because it depends on how your threads are scheduled. The outcome will be between 0 and 5.