I'm new to using wait() and notify() in Java and I'm getting an IllegalMonitorStateException.
Main Code
public class ThreadTest {
private static Integer state = 0;
public static void main(String[] args) {
synchronized(state) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
synchronized(state) {
state = 0;
while(state == 0) {
try {
state.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(state) {
state = 1;
state.notify();
}
}
}
}
I'm getting an IllegalMonitorStateException what state.notify() is called. Any ideas?
Edit: Based on answer below here is code that works. As a side note, I was first trying this with an enum which has the same problem of using Integer.
public class ThreadTest {
private static int state = 0;
private static Object monitor = new Object();
public static void main(String[] args) {
synchronized(monitor) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
state = 0;
while(state == 0) {
try {
for(int i = 0; i < 5; i++) {
System.out.println("Waiting " + (5 - i) + " Seconds");
Thread.sleep(1000);
}
monitor.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(monitor) {
state = 1;
monitor.notify();
}
}
}
}
This
private static Integer state = 0;
is equivalent to
private static Integer state = Integer.valueOf(0);
The invocation of valueOf(0) returns a reference to an Integer object, call it A.
You then do
synchronized(state) {
your thread acquires the lock on the object referenced by state, currently that is A.
You then do
state = 1;
which is equivalent to
state = Integer.valueOf(1);
which gives you a different reference to an Integer object, call it B, and assigns it to state. When you then call
state.notify();
you're invoking notify() on an object, B, for which your thread doesn't own the monitor. You can't call notify or wait on objects for which your thread doesn't own the monitor.
I was asked to write a two-threaded Java program in an interview. In this program one thread should print even numbers and the other thread should print odd numbers alternatively.
Sample output:
Thread1: 1
Thread2: 2
Thread1: 3
Thread2: 4
... and so on
I wrote the following program. One class Task which contains two methods to print even and odd numbers respectively. From main method, I created two threads to call these two methods. The interviewer asked me to improve it further, but I could not think of any improvement. Is there any better way to write the same program?
class Task
{
boolean flag;
public Task(boolean flag)
{
this.flag = flag;
}
public void printEven()
{
for( int i = 2; i <= 10; i+=2 )
{
synchronized (this)
{
try
{
while( !flag )
wait();
System.out.println(i);
flag = false;
notify();
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
public void printOdd()
{
for( int i = 1; i < 10; i+=2 )
{
synchronized (this)
{
try
{
while(flag )
wait();
System.out.println(i);
flag = true;
notify();
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
}
public class App {
public static void main(String [] args)
{
Task t = new Task(false);
Thread t1 = new Thread( new Runnable() {
public void run()
{
t.printOdd();
}
});
Thread t2 = new Thread( new Runnable() {
public void run()
{
t.printEven();
}
});
t1.start();
t2.start();
}
}
I think this should work properly and pretty simple.
package com.simple;
import java.util.concurrent.Semaphore;
/**
* #author Evgeny Zhuravlev
*/
public class ConcurrentPing
{
public static void main(String[] args) throws InterruptedException
{
Semaphore semaphore1 = new Semaphore(0, true);
Semaphore semaphore2 = new Semaphore(0, true);
new Thread(new Task("1", 1, semaphore1, semaphore2)).start();
new Thread(new Task("2", 2, semaphore2, semaphore1)).start();
semaphore1.release();
}
private static class Task implements Runnable
{
private String name;
private long value;
private Semaphore semaphore1;
private Semaphore semaphore2;
public Task(String name, long value, Semaphore semaphore1, Semaphore semaphore2)
{
this.name = name;
this.value = value;
this.semaphore1 = semaphore1;
this.semaphore2 = semaphore2;
}
#Override
public void run()
{
while (true)
{
try
{
semaphore1.acquire();
System.out.println(name + ": " + value);
value += 2;
semaphore2.release();
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
}
}
}
}
Well, there are many alternatives. I would probably use a SynchronousQueue instead (I don't like low-level wait/notify and try to use higher-level concurrency primitives instead). Also printOdd and printEven could be merged into single method and no additional flags are necessary:
public class App {
static class OddEven implements Runnable {
private final SynchronousQueue<Integer> queue = new SynchronousQueue<>();
public void start() throws InterruptedException {
Thread oddThread = new Thread(this);
Thread evenThread = new Thread(this);
oddThread.start();
queue.put(1);
evenThread.start();
}
#Override
public void run() {
try {
while (true) {
int i = queue.take();
System.out.println(i + " (" + Thread.currentThread() + ")");
if (i == 10)
break;
queue.put(++i);
if (i == 10)
break;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws InterruptedException {
new OddEven().start();
}
}
Is there any better way to write the same program?
Well, the thing is, the only good way to write the program is to use a single thread. If you want a program to do X, Y, and Z in that order, then write a procedure that does X, then Y, then Z. There is no better way than that.
Here's what I would have written after discussing the appropriateness of threads with the interviewer.
import java.util.concurrent.SynchronousQueue;
import java.util.function.Consumer;
public class EvenOdd {
public static void main(String[] args) {
SynchronousQueue<Object> q1 = new SynchronousQueue<>();
SynchronousQueue<Object> q2 = new SynchronousQueue<>();
Consumer<Integer> consumer = (Integer count) -> System.out.println(count);
new Thread(new Counter(q1, q2, 2, 1, consumer)).start();
new Thread(new Counter(q2, q1, 2, 2, consumer)).start();
try {
q1.put(new Object());
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
private static class Counter implements Runnable {
final SynchronousQueue<Object> qin;
final SynchronousQueue<Object> qout;
final int increment;
final Consumer<Integer> consumer;
int count;
Counter(SynchronousQueue<Object> qin, SynchronousQueue<Object> qout,
int increment, int initial_count,
Consumer<Integer> consumer) {
this.qin = qin;
this.qout = qout;
this.increment = increment;
this.count = initial_count;
this.consumer = consumer;
}
public void run() {
try {
while (true) {
Object token = qin.take();
consumer.accept(count);
qout.put(token);
count += increment;
}
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
}
How about a shorter version like this:
public class OddEven implements Runnable {
private static volatile int n = 1;
public static void main(String [] args) {
new Thread(new OddEven()).start();
new Thread(new OddEven()).start();
}
#Override
public void run() {
synchronized (this.getClass()) {
try {
while (n < 10) {
this.getClass().notify();
this.getClass().wait();
System.out.println(Thread.currentThread().getName() + ": " + (n++));
this.getClass().notify();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
There is a bit of a trick to kick-start the threads properly - thus the need to an extra notify() to start the whole thing (instead of have both processes wait, or required the main Thread to call a notify) and also to handle the possibility that a thread starts, does it's work and calls notify before the second thread has started :)
My initial answer was non-functional. Edited:
package test;
public final class App {
private static volatile int counter = 1;
private static final Object lock = new Object();
public static void main(String... args) {
for (int t = 0; t < 2; ++t) {
final int oddOrEven = t;
new Thread(new Runnable() {
#Override public void run() {
while (counter < 100) {
synchronized (lock) {
if (counter % 2 == oddOrEven) {
System.out.println(counter++);
}
}
}
}
}).start();
}
}
}
I want to replace await(),signalAll() with wait(),notifyAll() (java's default monitor) and my code listed below, the problem is that once thread get into waiting state. it never be notified again.. Thanks for your help.
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AccountThreadCommunicationDefault {
private static Account account = new Account();
private static Random random = new Random();
public static void main(String... args) {
ExecutorService es = Executors.newFixedThreadPool(2);
es.execute(new WithdrawTask());
es.execute(new DepositTask());
es.shutdown();
}
private static class WithdrawTask implements Runnable {
public void run() {
while (true) {
account.withdraw(random.nextInt(600));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private static class DepositTask implements Runnable {
public void run() {
while (true) {
account.deposit(random.nextInt(500));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private static class Account {
private Integer balance = 500;
private static Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// private Object object = new Object();
// public synchronized void deposit(int count) {
public void deposit(int count) {
try {
lock.lock();
System.out.print("当前账户余额:" + balance);
balance += count;
System.out.println(" 存款:" + count + " 账户余额(deposit): "
+ getBalance());
// synchronized (object) {
// object.notifyAll();
// }
synchronized (this) {
this.notify();
}
} catch (IllegalMonitorStateException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void withdraw(int count) {
try {
lock.lock();
while (balance < count) {
System.out.println("余额不足:" + getBalance() + " 等待存款..");
// synchronized (object) {
// object.wait();
// }
synchronized (this) {
this.wait();
}
System.out.print("当前账户余额:" + balance);
balance -= count;
System.out.println(" 取现:" + count + " 账户余额(withdraw): "
+ getBalance());
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public int getBalance() {
return this.balance;
}
}
}
You have a deadlock. The Withdraw task is waiting on the Account object's monitor, while holding the ReentrantLock locked. The Deposit task can not notify() the Account object monitor because it can't lock the ReentrantLock.
You need to wait() and notify() the same object that you are using as a mutex. Doesn't matter whether it's the ReentrantLock or the Account object's monitor. But it won't work the way you wrote it with two different locks.
I have created two runnable jobs: PrintEvenNumbersJob and PrintOddNumbersJob and spawned two threads to execute these jobs. This seems to work perfectly fine! But I smell something suspicious about this implementation. Can I have some comments and advice on this implementation?
The problem that I see with this implementation is that the program terminates only when thread1 gains the lock to the object lock first otherwise it print the odd first even second order and doesn't terminate unless I supply yet another statement "lock.notify" after for statement in PrintEvenNumbersJob (as in this implementation). My question here is how to make sure that thread1 is executed first.
public class PrintEvenNumbersJob implements Runnable {
private Object lock;
public PrintEvenNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i <= 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify(); // not required if thread1 gains lock first
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Object lock;
public PrintOddNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 1; i < 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();
}
}
}
public class EvenOddManager {
public static void main(String[] args) {
Object lock = new Object();
PrintEvenNumbersJob printEvenNumbersJob = new PrintEvenNumbersJob(lock);
PrintOddNumbersJob printOddNumbersJob = new PrintOddNumbersJob(lock);
Thread thread1 = new Thread(printEvenNumbersJob);
Thread thread2 = new Thread(printOddNumbersJob);
thread2.start();
thread1.start();
}
}
Have you try using Semaphores? It's easier because you don't need to worry about the order that wait and notify are called (if you call notify before the wait, it's "lost")
Sample code:
import java.util.concurrent.*;
public class Test {
private final Semaphore oddJobPermits = new Semaphore(0);
private final Semaphore evenJobPermits = new Semaphore(1);
private class EvenJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
evenJobPermits.acquire();
System.out.println(i * 2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
oddJobPermits.release();
}
}
}
}
private class OddJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
oddJobPermits.acquire();
System.out.println(i * 2 + 1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
evenJobPermits.release();
}
}
}
}
public void run() {
new Thread(new EvenJob()).start();
new Thread(new OddJob()).start();
}
public static void main(String[] args) {
new Test().run();
}
}
I believe you will need a referee:
public class Referee {
private boolean evensTurn = true;
public void waitMyTurn(boolean even) {
synchronized(this) {
while (even != evensTurn) {
try {
wait();
} finally {
}
}
}
}
public void done() {
synchronized(this) {
evensTurn = !evensTurn;
notify();
}
}
}
public class PrintEvenNumbersJob implements Runnable {
private Referee referee;
public PrintEvenNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(true);
System.out.println(i);
referee.done();
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Referee referee;
public PrintOddNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(false);
System.out.println(i);
referee.done();
}
}
}
I tried and tested this code. It works using Semaphore
public class TestSemaphore
{
public static void main(String[] args)
throws Exception
{
AtomicInteger count = new AtomicInteger();
Semaphore s = new Semaphore(1, true);
Semaphore t = new Semaphore(1, true);
OddNumberThread oThread = new OddNumberThread(count, s, t);
EvenNumberThread eThread = new EvenNumberThread(count, s, t);
eThread.start();
oThread.start();
}
static class EvenNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public EvenNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Even");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Make this thread wait until even thread starts, Order will be incorrect if removed these lines.
s.acquireUninterruptibly();
while (count.intValue() <= 10)
{
try
{
// Double checking to make it work
s.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
t.release();
}
}
}
}
static class OddNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public OddNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Odd");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Start this thread first and start printing, Order will be incorrect if removed these lines.
t.acquireUninterruptibly();
s.release();
while (count.intValue() <= 10)
{
try
{
t.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
s.release();
}
}
}
}
}
I am trying to create an implementation where multiple threads print alternate values of sequence. So here thread1 will print 1,4,7 thread2 will print 2,5,8 thread3 will print 3,6,9. I am using Atomic integer and modulo function.
Below implementation works fine in the sense that first thread prints 1,4,7 while second prints 2,5,8 and third prints 3,6,9 but problem is that sequence is not maintained i.e output can be like 1,3,2,4,5,7,8,6,9 while i want sequence to be maintained as proper threads shld print those values.
One condition is i don't want to use synchronize. [Just for learning purpose]
import java.util.concurrent.atomic.AtomicInteger;
public class ThreeThreadsOrderedLockLess {
AtomicInteger sharedOutput = new AtomicInteger(0);
public static void main(String args[]) {
ThreeThreadsOrderedLockLess t = new ThreeThreadsOrderedLockLess();
ThreadTasks t1 = t.new ThreadTasks(0);
ThreadTasks t2 = t.new ThreadTasks(1);
ThreadTasks t3 = t.new ThreadTasks(2);
Thread ts1 = new Thread(t1);
Thread ts2 = new Thread(t2);
Thread ts3 = new Thread(t3);
ts1.start();
ts2.start();
ts3.start();
}
private class ThreadTasks implements Runnable {
private final int threadPosition;
public ThreadTasks(int threadPosition) {
super();
this.threadPosition = threadPosition;
}
#Override
public void run() {
while (sharedOutput.get() < 9) {
if (sharedOutput.get() % 3 == this.threadPosition) {
System.out.println("Printing output for Thread: "
+ this.threadPosition + " "
+ sharedOutput.incrementAndGet());
}
}
}
}
}
You should print first, and increment after:
int value = sharedOutput.get() + 1;
System.out.println("Printing output for Thread: "
+ this.threadPosition + " "
+ value);
sharedOutput.incrementAndGet();
That said, all the threads are busy looping, which will lead to 100% CPU usage. You should synchronize the threads instead.
Below code snippet will print numbers in sequence and all threads will be terminated gracefully after the task.
Used AtomicInteger, which is thread-safe for printing the numbers and same logic can be applied to print as till any number with any number of threads.
import java.util.concurrent.atomic.AtomicInteger;
public class PrintNumSequence
{
public static void main(String[] args)
{
AtomicInteger atomicInteger = new AtomicInteger(0);
new NumPrinter(atomicInteger, 0).start();// thread0
new NumPrinter(atomicInteger, 1).start();// thread1
new NumPrinter(atomicInteger, 2).start();// thread2
}
}
class NumPrinter extends Thread
{
private AtomicInteger atomicInteger;
private int threadNum;
public NumPrinter(AtomicInteger atomicInteger, int threadNum)
{
this.atomicInteger = atomicInteger;
this.threadNum = threadNum;
}
#Override
public void run()
{
int num = atomicInteger.intValue();
do
{
synchronized (atomicInteger)
{
num = atomicInteger.intValue();
// If number is 9 then stop.
if (num > 9)
{
atomicInteger.notifyAll();
break;
}
// 3 is number of threads
if ((num % 3) == threadNum)
{
System.out.println("Thread-" + threadNum + " -->" + num);
num = atomicInteger.incrementAndGet();
}
atomicInteger.notifyAll();
try
{
atomicInteger.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
} while (true);
}
}
This is because the time slice for each thread is determined by the OS. So it is possible that thread x increments the shared number but before printing the time slice is passed to the next thread y which now reads the shared number and prints it after incrementing (assuming that thread y got more time than thread x to increament and print the shared number)
.
use wait(), notify(), notifyall() methods of the Java.
you can also take a look at this Tutorial of these methods.
Hope this would be helpful to solve your issue. . .
the output of this example is as under.
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
This should work:
package com.sid;
import java.util.concurrent.atomic.AtomicInteger;
public class NumberSequence {
private AtomicInteger sharedOutput = new AtomicInteger(0);
private Object object = new Object();
public static void main(String args[]) {
NumberSequence t = new NumberSequence();
ThreadTasks t1 = t.new ThreadTasks(0);
ThreadTasks t2 = t.new ThreadTasks(1);
ThreadTasks t3 = t.new ThreadTasks(2);
Thread ts1 = new Thread(t1);
Thread ts2 = new Thread(t2);
Thread ts3 = new Thread(t3);
ts1.start();
ts2.start();
ts3.start();
}
private class ThreadTasks implements Runnable {
private final int threadPosition;
public ThreadTasks(int threadPosition) {
super();
this.threadPosition = threadPosition;
}
#Override
public void run() {
while (sharedOutput.get() < 10) {
synchronized (object) {
if (sharedOutput.get() % 3 == this.threadPosition) {
if(sharedOutput.get() < 10)
System.out.println("Printing output for Thread: "
+ this.threadPosition + " "
+ sharedOutput.incrementAndGet());
}
}
}
}
}
}
Proper synchronization would help you get the clear answer. I've improved the implementation, you should solve your questions.
int threadId;
int moduluos;
int numOfThreads;
public ThreadTasks(int id, int nubOfThreads) {
threadId = id;
this.numOfThreads = nubOfThreads;
moduluos = threadId%numOfThreads;
}
public void run() {
print();
}
private void print() {
try {
while (true) {
synchronized (monitor) {
if (number.get() % numOfThreads != moduluos) {
monitor.wait();
} else {
System.out.println("ThreadId [" + threadId
+ "] printing -->"
+ number.getAndIncrement());
monitor.notifyAll();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package test.mk.thread;
import java.util.concurrent.atomic.AtomicInteger;
public class MkThread2 {
int nextThreadToRun = 1;
int[] arr = {1,2,3,4,5,6,7,8,9,10,11};
AtomicInteger nextArrayIndex = new AtomicInteger(0);
boolean token = true;
public static void main(String[] args) {
MkThread2 mkThread = new MkThread2();
Thread t1 = new Thread(new Worker2(1, mkThread));
Thread t2 = new Thread(new Worker2(2, mkThread));
Thread t3 = new Thread(new Worker2(3, mkThread));
t1.start();
t2.start();
t3.start();
}
}
class Worker2 implements Runnable{
volatile int threadNo;
private MkThread2 mkThread;
private String threadName;
Worker2(int threadNo, MkThread2 mkThread){
this.threadNo = threadNo;
this.mkThread = mkThread;
this.threadName = "Thread:"+threadNo ;
}
public void run(){
try{
synchronized (mkThread) {
while(mkThread.token){
while(threadNo != mkThread.nextThreadToRun){
mkThread.wait();
}
if(mkThread.token){//double checking
System.out.print(threadName+ "->" + mkThread.arr[mkThread.nextArrayIndex.get()]);
if(threadNo == 3) System.out.println();
mkThread.nextThreadToRun = getNextThread(threadNo);
if(mkThread.nextArrayIndex.get() == mkThread.arr.length-1){
mkThread.token = false;
}
mkThread.nextArrayIndex.incrementAndGet();
}
mkThread.notifyAll();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
private int getNextThread(int threadNo){
int result = -1;
switch (threadNo) {
case (1):
result = 2;
break;
case (2):
result = 3;
break;
case (3):
result = 1;
break;
}
return result;
}
}
import java.util.concurrent.atomic.AtomicInteger;
public class Print123456789 {
public static void main(String[] args) {
print p1 = new print(0);
print p2 = new print(1);
print p3 = new print(2);
Thread t1 = new Thread(p1);
Thread t2 = new Thread(p2);
Thread t3 = new Thread(p3);
t1.start();
t2.start();t3.start();
}
}
class print implements Runnable {
private int threadNumber;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
public print(int threadNumber) {
super();
this.threadNumber = threadNumber;
}
public void run(){
try{
while(atomicInteger.get() < 10){
synchronized (atomicInteger) {
if((atomicInteger.get()%3) == this.threadNumber){
System.out.println(atomicInteger.getAndIncrement() + " Thread :" + this.threadNumber );
atomicInteger.notifyAll();
}
else
atomicInteger.wait();
}
}
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
This can be better implemented using blocking queues. Define a worker holding a blocking queue. The workers waits on the queue until it receives a number in it. It prints the number it receives, increments it and passes it on to the next worker in the chain. Refer here for the full solution.
package threeThread;
class Task implements Runnable {
String message;
ThreeThread lock;
int i = 0;
int p;
public Task(String text, ThreeThread obj, int p) {
message = text;
this.lock = obj;
this.p = p;
}
#Override
public void run() {
while(true) {
synchronized (lock) {
while(!((lock.status % 3) == 0) && p == 1){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while(!((lock.status % 3) == 1) && p == 2){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while(!((lock.status % 3) == 2) && p == 3){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("thread: " + p + " : " + message);
lock.status++;
lock.notifyAll();
}
}
}
}
public class ThreeThread {
volatile int status = 0;
public static void main(String[] args) {
ThreeThread lock = new ThreeThread();
Thread t1 = new Thread(new Task("Hello", lock,1));
Thread t2 = new Thread(new Task("Good", lock,2));
Thread t3 = new Thread(new Task("Morning", lock,3));
t1.start();
t2.start();
t3.start();
}
}
I am putting code to print 1-100 using 5 threads. One can use any number of thread to print output in round robin fashion.
Basic concept is to lock one object and notify other for executing the printing of value.
public class PrintOneToHundredUsing5Threads {
public static void main(String[] args) {
List<Object> objList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
objList.add(new Object());
}
for (int i = 0; i < 5; i++) {
Thread t = new Thread(new PrintThread(objList.get(i), objList.get((i + 1) % 5)));
t.setName("Thread" + i);
t.start();
}
}
}
class PrintThread implements Runnable {
Object current;
Object next;
volatile static int i = 1;
PrintThread(Object cur, Object next) {
this.current = cur;
this.next = next;
}
#Override
public void run() {
for (; i <= 100;) {
synchronized (current) {
synchronized (next) {
next.notify();
System.out.println(Thread.currentThread().getName() + " Value : " + i++);
}
try {
current.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
You can use below code to print sequential numbers using multiple threads -
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadCall extends Thread {
private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
private ThreadCall next;
public void setNext(ThreadCall t) {
this.next = t;
}
public void addElBQ(int a) {
this.bq.add(a);
}
public ThreadCall(String name) {
this.setName(name);
}
#Override
public void run() {
int x = 0;
while(true) {
try {
x = 0;
x = bq.take();
if (x!=0) {
System.out.println(Thread.currentThread().getName() + " =>" + x);
if (x >= 100) System.exit(0); // Need to stop all running threads
next.addElBQ(x+1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int THREAD_COUNT = 10;
List<ThreadCall> listThread = new ArrayList<>();
for (int i=1; i<=THREAD_COUNT; i++) {
listThread.add(new ThreadCall("Thread " + i));
}
for (int i = 0; i < listThread.size(); i++) {
if (i == listThread.size()-1) {
listThread.get(i).setNext(listThread.get(0));
}
else listThread.get(i).setNext(listThread.get(i+1));
}
listThread.get(0).addElBQ(1);
for (int i = 0; i < listThread.size(); i++) {
listThread.get(i).start();
}
}
}
Hope this will resolve your problem.
public class PrintThreadsInSerial {
public static void main(String[] args) {
Thread t = new Thread(new Job());
t.start();
}
}
class Job implements Runnable {
#Override
public void run() {
while (true) {
for (int i = 1; i <= 3; i++) {
System.out.println(i);
}
}
}
}
The ThreadSynchronization class can be used to print numbers between 'n' no. of threads in sequence.
The logic is to create a common object between each of the consecutive threads and use 'wait', 'notify' to print the numbers in sequence.
Note: Last thread will share an object with the first thread.
You can change the 'maxThreads' value to increase or decrease the number of thread in the program before running it.
import java.util.ArrayList;
import java.util.List;
public class ThreadSynchronization {
public static int i = 1;
public static final int maxThreads = 10;
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
for (int i = 0; i < maxThreads; i++) {
list.add(new Object());
}
Object currObject = list.get(maxThreads - 1);
for (int i = 0; i < maxThreads; i++) {
Object nextObject = list.get(i);
RunnableClass1 a = new RunnableClass1(currObject, nextObject, i == 0 ? true : false);
Thread th = new Thread(a);
th.setName("Thread - " + (i + 1));
th.start();
currObject = list.get(i);
}
}
}
class RunnableClass implements Runnable {
private Object currObject;
private Object nextObject;
private boolean firstThread;
public RunnableClass(Object currObject, Object nextObject, boolean first) {
this.currObject = currObject;
this.nextObject = nextObject;
this.firstThread = first;
}
#Override
public void run() {
int i = 0;
try {
if (firstThread) {
Thread.sleep(5000);
firstThread = false;
System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
synchronized (nextObject) {
nextObject.notify();
}
}
while (i++ < Integer.MAX_VALUE) {
synchronized (currObject) {
currObject.wait();
}
System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
Thread.sleep(1000);
synchronized (nextObject) {
nextObject.notify();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class PrintSeqNumUsingAltThreads {
public static void main(String[] args) {
AtomicInteger counter = new AtomicInteger(0);
int numThreads = 3;
Thread t1 = new Thread(new SeqNumPrinter(counter, 0, numThreads));
Thread t2 = new Thread(new SeqNumPrinter(counter, 1, numThreads));
Thread t3 = new Thread(new SeqNumPrinter(counter, 2, numThreads));
t1.currentThread().setName("T1");
t2.currentThread().setName("T2");
t3.currentThread().setName("T3");
t1.start();
t2.start();
t3.start();
}
}
public class SeqNumPrinter implements Runnable {
AtomicInteger atmCounter;
Integer threadPosition;
Integer numThreads;
public SeqNumPrinter(AtomicInteger counter, int position, int numThreads) {
this.atmCounter = counter;
this.threadPosition = position;
this.numThreads = numThreads;
}
#Override
public void run() {
while (atmCounter.get() < 10) {
if (atmCounter.get() % numThreads == threadPosition) {
System.out.println("Printing value : " + atmCounter.getAndIncrement() + ", by thread : " +
Thread.currentThread().getName());
}
}
}
}
Output :
Printing value : 0, by thread : Thread-0 Printing value : 1, by
thread : Thread-1 Printing value : 3, by thread : Thread-0
Printing value : 2, by thread : Thread-2 Printing value : 4, by
thread : Thread-1 Printing value : 6, by thread : Thread-0
Printing value : 5, by thread : Thread-2 Printing value : 7, by
thread : Thread-1 Printing value : 9, by thread : Thread-0
Printing value : 8, by thread : Thread-2