I need to initialize an Array of n Threads. Each Thread represents a number which randomly initialized in the Thread's Object creation.
The program should run m iterations. On each iteration, the Threads number needs to be updated. If both left and right neighbors in the Array are bigger than this Thread then the Thread's value will get +1 in the next iteration. If both neighbors values are lower then the Thread's value then the Thread's value will get -1. Otherwise, the Thread's value will not change.
The code starts from a code line in a GUI class. The line is:
Controller cont = new Controller(n,m)
The code enters updated method in class Controller just once and then all the Threads are going to sleep without implementing updated method.
Why is that?
This is my code:
public class Threads extends Thread
{
private int num;
private Controller cont;
private int toUpdate;
private int index;
public Threads(Controller c, int i)
{
num = (int)(Math.random() * 100 + 1); // random number between 1-100
cont = c;
index = i;
}
public void run()
{
for(int j = 1; j <= cont.getIterations(); j++)
{
toUpdate = cont.checkValue(this, this.getIndex());
cont.finished();
cont.threadWait();
num += toUpdate;
cont.updated();
cont.threadWait();
}
}
public int getValue()
{
return this.num;
}
public int getIndex()
{
return this.index;
}
}
public class Controller
{
private Threads[] threadsArray;
private int iterations;
private boolean finished = false;
private static int numOfThreads;
public Controller(int n, int m)
{
threadsArray = new Threads[n];
for(int i=0; i < threadsArray.length; i++)
threadsArray[i] = new Threads(this, i);
iterations = m;
numOfThreads = n;
printResults();
for(int i=0; i < threadsArray.length; i++)
threadsArray[i].start();
}
public synchronized void threadWait()
{
while(!finished)
{
try{ wait(); }
catch(InterruptedException e) {}
}
numOfThreads++;
waitForAll();
if(numOfThreads == threadsArray.length)
{
finished = false;
notifyAll();
}
}
public int checkValue(Threads t, int ind) //returns the thread's value to be updated. 1,-1 or 0.
public int getIterations()
{
return this.iterations;
}
public synchronized void finished()
{
numOfThreads--;
notifyAll();
if(numOfThreads == 0)
finished = true;
}
public void iteration()
{
for(int i=0; i < threadsArray.length; i++)
threadsArray[i].start();
}
public synchronized void updated()
{
numOfThreads--;
if(numOfThreads == 0)
{
printResults();
finished = true;
notifyAll();
}
}
public synchronized void waitForAll()
{
while(numOfThreads != threadsArray.length)
{
try{ wait(); }
catch(InterruptedException e) {}
}
}
public void printResults() // prints the result on each iteration.
}
Related
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();
}
}
}
Answer: as Maarten Bodewes pointed out, my mistake was to not call allChecked in setCol and setRow.
This problem has puzzled me for a long time, please help me,thanks.
This is my java code.
package com.concurrent.example;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* P683
*/
class CircularSet {
private int[] array;
private int len;
private int index = 0;
public CircularSet (int size) {
array = new int[size];
len = size;
for (int i = 0; i < size; i++) {
array[i] = -1;
}
}
public synchronized void add(int i ) {
array[index] = i;
index = ++index % len;
}
public synchronized boolean contains(int val) {
for (int i = 0; i < len; i++) {
if(array[i] == val) {
return true;
}
}
return false;
}
}
public class SerialNumberChecker {
private static final int SIZE = 10;
private static CircularSet serials = new CircularSet(1000);
private static ExecutorService exec = Executors.newCachedThreadPool();
private static int serial;
static class SerialChecker implements Runnable {
#Override
public void run() {
while(true) {
//int serial;
synchronized (serials) {
serial = SerialNumberGenerator.nextSerialNumber();
}
if (serials.contains(serial)) {
System.out.println("Duplicate: " + serial);
System.exit(0);
}
System.out.println(serial);
serials.add(serial);
}
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < SIZE; i++) {
exec.execute(new SerialChecker());
if (args.length > 0) {
TimeUnit.SECONDS.sleep(new Integer(args[0]));
System.out.println("No duplicates detected");
System.exit(0);
}
}
}
}
It can stop, but when i uncomment //int serial;The result is different,it can't stop.Why does this temporary variable have a different result than the static variable of the external class. Is this the reason of using a thread?
The code of SerialNumberGenerator:
public class SerialNumberGenerator {
private static volatile int serialNumber = 0;
public static int nextSerialNumber() {
return serialNumber ++; //Not thread-safe
}
}
With private static int serial, all SerialNumberCheckers share the same serial. For example:
Thread1 set serial = 1
Thread2 set serial = 2
Thread1 put 2 into CircularSet.
Thread2 found it duplicate and exit.
However, if you declare another int serial in the run method, It will shadow the private static int serial, which means all threads has its own serial and they will assign & check it. Since the generation of serial is in the synchronized block, there will be no duplicates.
Now I'm struggling with the task from the title. I create X threads, each of them prints Y equal digits (getting from constructor, for example "11111", "222222" etc) for Z times in cycle. So the result looks like:
111111111
222222222
333333333
111111111
222222222
333333333
for X = 3, Y = 9 and Z = 2.
Firstly I've solved this issue using sleep, interrupt and passing "next" thread to the constructor of previous one. One interrupts another etc. Next step is to get the same output using wait/notify instead sleep and interrupt. As far as I can see, it's neccesary to create the shared monitor object, to invoke wait after every printing and in a some moment " I should invoke notifyAll.
Current code is:
public class PrinterController {
private static final int THREADS_NUMBER = 5;
public static void main(String[] args) {
Printer[] printers = new Printer[THREADS_NUMBER];
for (int i = 0; i < THREADS_NUMBER; i++) {
printers[i] = new Printer(i);
printers[i].start();
}
}
}
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
private static final Object monitor = new Object();
public Printer(int digit) {
this.digit = digit;
}
#Override
public void run() {
synchronized (monitor) {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
printLine();
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
}
}
Could you help to improve it? I found similar tasks but they don't contain appropriate answers. Thanks.
Final solution based on the Nadir's answer:
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
static Object monitor = new Object();
static Integer counter = 0;
public Printer(int digit) {
this.digit = digit;
}
#Override
public void run() {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
synchronized (monitor) {
while (digit != counter) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
printLine();
monitor.notifyAll();
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
counter = (counter + 1) % PrinterController.THREADS_NUMBER;
}
}
It can be accomplished with a class used to synchronize the threads (and even make sure they are orderer). All threads would share the same instance.
public class Synchronizer
{
private int nextThread;
private int maxNumThreads;
public Synchronizer(int numThreads)
{
maxNumThreads = numThreads;
nextThread = 0;
}
public void doSync(int threadId) throws Exception
{
synchronized(this)
{
while(nextThread != threadId)
{
wait();
}
}
}
public void threadDone(int threadId) throws Exception
{
synchronized(this)
{
nextThread = (threadId + 1) % maxNumThreads;
notifyAll();
}
}
}
On your thread's run(), you would call doSync() before printing anything. Then you would put the code for printing, and afterwards, you would call threadDone(), allowing the next thread to be released. The id is used to enforce an order.
Im trying to make 2 threads that read/write to a counter using thread safe methods.
I have written some code to try test this but the read thread just reads the counter at its max (1000)
Main:
public static void main(String[] args) {
Counter c = new Counter();
Thread inc = new Increment(c);
Thread read = new Read(c);
inc.start();
read.start();
}
Counter:
public class Counter {
private int count;
public Counter() {
count = 0;
}
public synchronized void increment() {
count++;
}
public synchronized int getVal() {
return count;
}
}
Increment:
public class Increment extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Increment(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
myCounter.increment();
}
}
}
Read:
public class Read extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Read(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
System.out.println(myCounter.getVal());
}
}
}
Would I be better off using Atomic Integer to hold the value of the counter to allow me to safely increment it and get the value?
Your code is perfectly fine as is. It just so happened that your increment thread finished all its increments before the read thread got a chance to read. 1,000 increments takes almost no time at all.
If you want interleave execution of Read thread and Increment thread much more often then the natural operating system thread pre-emption, just make each thread give up their lock (by calling <lockedObject>.wait() followed by <lockedObject>.notify() or notifyAll() in the respective run() methods:
[In Reader]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
System.out.println(myCounter.getVal());
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
[In Increment]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
myCounter.increment();
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Upping the MAX constant to 1_000_000_000 (1 billion) made the treads interleave as well every now and then (on my machine interleave happened just by gazing at few printouts between 150 and 400_000 iterations).
It's a little program written with a purpose of studying multithreading. I expected to get in main method different random numbers after run. About 4 numbers per second. But I got many thousands of zeros. Where is an error?
Main Class:
public class Main {
public static void main(String[] args) {
ExternalWorld externalWorld = new ExternalWorld();
externalWorld.start();
int x = 0;
while (true) {
while(!externalWorld.signal){
System.out.println("qqq");}
System.out.println(++x + ") " + externalWorld.getAnInt());
}
}
}
ExternalWorld Class:
import java.util.Random;
public class ExternalWorld extends Thread {
private int anInt = 0;
public boolean signal = false;
#Override
public void run() {
Random random = new Random(100);
while(true) {
anInt = random.nextInt(100);
signal = true;
try {
Thread.sleep(200);
signal = false;
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getAnInt() {
if (!signal) {
int p = 1 / 0;
}
int result = anInt;
anInt = 0;
return result;
}
}
problem:
private int anInt = 0;
public boolean signal = false;
You are access those variables from one thread to another thus giving you 0 and false on the main thread
solution:
use volatile keyword to access those variables from multiple threads
sample:
private volatile int anInt = 0;
public volatile boolean signal = false;