I'm trying to accomplish the following:
- Get two inputs from the user (
length
andamountOfCycles
) - Create an array containing
length
amount of Threads. Each containing an integervalue
within the range[1, 100]
. - Loop the
amountOfCycles + 1
amount of times and do the following every iteration:- Print the values of the array.
- Update each value in the array based on its (cyclic) neighbors:
- If the value is smaller than that of both neighbors: increase the value by 1
- If the value is larger than that of both neighbors: decrease the value by 1
- If the current value is smaller than or equal to one neighbor, and larger than or equal to the other neighbor: leave the value unchanged
Updating these values based on their neighbors is the reason for it to be multi-threading. Please note that this is just something to practice multi-threading. I'm easily able to do what's described above by simply removing threads all together and create a copy of the array (which I already did).
Here is my code thus far:
import java.util.Arrays;
import java.util.Scanner;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Main{
Cell[] cells;
CyclicBarrier barrier;
int length, amountOfCycles;
Main(){
Scanner stdin = new Scanner(System.in);
length = stdin.nextInt();
amountOfCycles = stdin.nextInt();
barrier = new CyclicBarrier(length);
cells = new Cell[length];
for(int i=0; i<length; i++)
cells[i] = new Cell(i);
}
public static void main(String[] args){
Main program = new Main();
program.start();
}
void start(){
for(int i=0; i<length; i++)
cells[i].run();
for(int cycle = amountOfCycles; cycle >= 0; cycle--)
System.out.println(Arrays.toString(cells));
}
class Cell implements Runnable{
int value,
index;
Cell(int i){
index = i;
value = (int)(Math.random() * 100) + 1; // Random integer within the range [1, 100]
}
@Override
public void run(){
try{
// Wait for the start of the cycle:
barrier.wait();
// Determine the increment for the value of this cell:
// Get the values of the neighbors:
int valueLeftNeighbor = cells[(length - index - 1) % length].value,
valueRightNeighbor = cells[(index + 1) % length].value,
// And create an increment-integer with default value 0:
increment = 0;
// If the current value is smaller than that of both neighbors:
if(value < valueLeftNeighbor && value < valueRightNeighbor){
// Increase the current value by 1
increment = 1;
}
// If the current value is larger than that of both neighbors:
if(value > valueLeftNeighbor && value > valueRightNeighbor){
// Decrease the current value by 1
increment = -1;
}
// If the current value is smaller than or equal to one neighbor,
// and larger than or equal to the other neighbor:
// Leave the value the same (so increment stays 0)
// Wait until every cell is done calculating its new value:
barrier.await();
// And then actually update the values of the cells
value += increment;
}catch(Exception ex){
System.err.println("Exception occurred! " + ex);
ex.printStackTrace();
}
}
@Override
public String toString(){
return Integer.toString(value);
}
}
}
Which is based on this SO question and answer and its accepted answer.
What my code above currently does:
It prints the array with random values amountOfCycles + 1
times, but doesn't change any value in between cycles. This is due to the IllegalMonitorStateExceptions
I get. Probably because I need a synchronized(barrier){ ... }
somewhere, because the barrier
is in the class Main
instead of Cell
? Adding it to the run
-method of the Cell
class however causes the program to not print anything anymore, nor terminate..
Here in my code above in an online compilers to see the current (incorrect) result.
What I expect it to do:
Modify the values in the array after every cycle.