Threads not waking up after notifyAll() is called - java

The question is to create 3 threads, one prints a random number every second, if the number is even a second thread squares it and if it odd a third thread cubes it. This should occur a given number of times(in my code it is infinite, will edit that out later). My issue is that after the first iteration(i.e. a random number is created, the correct thread wakes up and does its operation) the second/third threads don't wake up after notifyAll() is called again. My code is shown below with sample output. I've added a few print statements for debugging purposes:
package com.company;
import java.util.*;
class RandomNumber implements Runnable{
int randomNum = 0;
Random rand = new Random();
boolean flag = false;
public RandomNumber() {
Thread newThread = new Thread(this,"Random Number");
newThread.start();
}
#Override
public synchronized void run()
{
while(flag == false) {
System.out.println("random num thread");
try {
randomNum = rand.nextInt(100) + 1;
System.out.println(randomNum);
flag = true;
notifyAll();
//System.out.println(flag);
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
}
class SquareNumber implements Runnable{
RandomNumber randomNumOb;
public SquareNumber(RandomNumber randNumObject){
this.randomNumOb = randNumObject;
Thread squareThread = new Thread(this, "Square thread");
squareThread.start();
}
#Override
public synchronized void run() {
System.out.println("square thread before while");
while(randomNumOb.flag == true) {
System.out.println("square thread");
if (randomNumOb.randomNum % 2 == 0)
{
System.out.println("Number is even so square of " + randomNumOb.randomNum + " is: " + (randomNumOb.randomNum * randomNumOb.randomNum));
try {
randomNumOb.flag = false;
wait();
}catch(Exception e){
System.out.println("Exception caught");
}
}
else {
try {
System.out.println("inside square else");
wait();
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
System.out.println("square thread after while");
}
}
class CubeNumber implements Runnable{
RandomNumber randomNumOb;
public CubeNumber(RandomNumber randNumObject){
this.randomNumOb = randNumObject;
Thread squareThread = new Thread(this, "Square thread");
squareThread.start();
}
#Override
public synchronized void run() {
System.out.println("cube thread before while");
while(randomNumOb.flag == true) {
System.out.println("cube thread");
if (randomNumOb.randomNum % 2 == 1) {
System.out.println("Number is odd so cube of " + randomNumOb.randomNum + " is: " + (randomNumOb.randomNum * randomNumOb.randomNum * randomNumOb.randomNum));
try {
randomNumOb.flag = false;
wait();
}catch (Exception e){
}
}
else {
try {
System.out.println("inside cube else");
//randomNumOb.flag = false;
wait();
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
System.out.println("cube thread after while");
}
}
public class Main {
public static void main(String[] args) {
RandomNumber random = new RandomNumber();
SquareNumber square = new SquareNumber(random);
CubeNumber cube = new CubeNumber(random);
}
}
Sample output:
random num thread
81
square thread before while
square thread
inside square else
cube thread before while
cube thread
Number is odd so cube of 81 is: 531441
random num thread
68
It seems like neither the square or cube thread wakes up after this and can't figure out why. Any help would be appreciated.

For locking and wait/notify to work there needs to be a shared lock.
There is an "intrinsic lock" which is baked into each object. The lock works as a communications hub for wait and notify. Putting synchronized on an instance method means that a thread calling that method acquires the intrinsic lock on the instance when it enters the method, and releases the intrinsic lock when it leaves. The wait/notify/notifyAll methods can be called only by a thread holding the intrinsic lock.
When a thread calls wait, that releases the lock and the thread goes dormant until it receives a notification (or gets interrupted). The lock keeps track of which threads are currently waiting on it, that's called the waitset.
When a thread calls notify, that tells the scheduler to pick a thread from the lock's waitset and send it a notification. The notifyAll method is the same except it wakes up all the other threads in the waitset.
That is how locking determines which waiting thread gets notified.
So in the posted code, each of these Runnables acquires its own intrinsic lock and there is no sharing. the wakeup notification has to be caused by another thread that has acquired the lock that the waiting thread called wait on.
Here you could create a common lock in the entrypoint class
final Object lock = new Object(); // value referenced by lock must not change
and pass it into the different Runnables in the constructor such as:
public SquareNumber(RandomNumber randNumObject, Object lock){
this.lock = lock;
...
so they use the same lock. Then change wait and notify method calls to use that shared lock object, and change the synchronized methods to synchronized blocks that pass in the lock.
Btw about the sleep added to the RandomNumber runnable: the notifyAll doesn't take effect until the current thread releases the lock (since each waiting thread has to acquire the lock in order to leave the wait method). Sleeping here doesn't do anything to give the notification time to work, it just prevents anything from happening.

CubeNumber and SquareNumber both wait all for notifications on their own object - not for notifications on the random object. So they never get notified.
package com.company;
import java.util.*;
class RandomNumber implements Runnable{
int randomNum = 0;
Random rand = new Random();
boolean flag = false;
public RandomNumber() {
Thread newThread = new Thread(this,"Random Number");
newThread.start();
}
#Override
public void run()
{
while(flag == false) {
System.out.println("random num thread");
try {
randomNum = rand.nextInt(100) + 1;
System.out.println(randomNum);
flag = true;
synchronized(this) {
notifyAll();
}
//System.out.println(flag);
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
class CubeNumber implements Runnable{
RandomNumber randomNumOb;
public CubeNumber(RandomNumber randNumObject){
this.randomNumOb = randNumObject;
Thread squareThread = new Thread(this, "Square thread");
squareThread.start();
}
#Override
public synchronized void run() {
System.out.println("cube thread before while");
while(randomNumOb.flag == true) {
System.out.println("cube thread");
if (randomNumOb.randomNum % 2 == 1) {
System.out.println("Number is odd so cube of " + randomNumOb.randomNum + " is: " + (randomNumOb.randomNum * randomNumOb.randomNum * randomNumOb.randomNum));
try {
randomNumOb.flag = false;
synchronised(randomNumOb) {
randomNumOb.wait();
}
}catch (Exception e){
}
}
else {
try {
System.out.println("inside cube else");
//randomNumOb.flag = false;
wait();
} catch (Exception e) {
System.out.println("Exception Caught");
}
}
}
System.out.println("cube thread after while");
}
same with the square version.
But the added problem is that you have no guaranty that both the cube and the square methods will run within the sleep second of randomnumber.
Possibly a sempahor might be of use here.

Related

Why count only one file

Create a synchronous multithreaded system to determine the total of all integers or fractions in three text files. If a stream is blocked, it must display its name as "LOCKED". Why count only one file (Thread with lock)? What the programs display:Thread-0 Locked!
Thread-2 Locked!
123.321 322099, it's only for one file
import java.io.*;
import java.util.*;
import java.util.concurrent.locks.*;
public class Dispatcher {
public static void main(String[] args) throws InterruptedException {
SumOfDigits sumOfDigits = new SumOfDigits();
Thread thread = new Handler(new File("text.txt"), sumOfDigits);
Thread thread2 = new Handler(new File("text2.txt"), sumOfDigits);
Thread thread3 = new Handler(new File("text3.txt"), sumOfDigits);
thread.start();
thread2.start();
thread3.start();
thread.join();
thread2.join();
thread3.join();
System.out.println(sumOfDigits.resultDouble + " " + sumOfDigits.resultInt);
}
}
class SumOfDigits {
double resultDouble;
int resultInt;
Lock lock = new ReentrantLock();
void sum(File file) {
try (Scanner sc = new Scanner(file)) {
int tempInt = 0;
double tempDouble = 0;
while (sc.hasNext()) {
String num = sc.next();
if (num.contains(".")) {
tempDouble += Double.parseDouble(num);
} else {
tempInt += Integer.parseInt(num);
}
}
boolean flag = lock.tryLock();
if (flag) {
try {
resultDouble += tempDouble;
resultInt += tempInt;
} catch (Exception e) {
} finally {
lock.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " Locked!");
}
} catch (Exception e) {
}
}
}
class Handler extends Thread {
File file;
SumOfDigits sumOfDigits;
Handler(File file, SumOfDigits sumOfDigits) {
this.file = file;
this.sumOfDigits = sumOfDigits;
}
#Override
public void run() {
sumOfDigits.sum(file);
}
}
The ReentrantLock maintains a count of how many times it has been locked by the current thread. This count is decremented every time you call unlock() and the lock is release when the count reaches zero. Thus, to unlock the lock, you must call unlock() as many times as you have called lock() or tryLock().
In your code, you call tryLock() and if it is successful, you then call lock() inside the try/finally block and then you call unlock() once.
The first thread to lock the ReentrantLock will thus increment the count to two but only decrement the count to one, so the lock is never released. Therefore, no other thread can ever acquire the lock.
You should use tryLock() or lock() to the lock the ReentrantLock, not both.

Why do we use the synchronized block in this class method?

I have been learning multithreading in Java since recently and I encountered an example in the book. It goes something like this.
class NewThread implements Runnable {
String name;
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start();
}
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
while(suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
synchronized void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class Te {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming thread One");
ob2.mysuspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
ob2.myresume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Now in this example as you can see, there is a resume and a suspend method which gets called a couple of times in the program's main method. But when I remove the synchronized block in the run method, it displays an error something like this.
Exception in thread "Two" java.lang.IllegalMonitorStateException
I acually wanted to know, why do we need the synchronized block for the while statement. Doesn't the while resume when the value of suspendFlag change?
Here's what could happen if there was no synchronization:
Thread A could check suspendFlag and find it to be true,
Thread B could set suspendFlag=false; and then call notify();
Thread A could then call wait() (because suspendFlag was true when it checked.), and now Thread A is hung, waiting for a notification that will never happen.
The synchronization prevents thread B from changing the suspendFlag in between the moment when thread A checked it, and the moment when thread A actually begins to wait for the notification.

Java looping Threads using CyclicBarrier

I have a program with this general structure:
init
create CyclicBarrier
initialise all threads, attaching to barrier
*start all threads*
wait for join
display stats
*start all threads*
perform calculation
await barrier
My problem is I need the threads' run() method to keep looping until a certain condition is met, but pausing after every iteration to let all threads synchronise.
I've already tried attaching a Runnable method to the barrier, but this ends up requiring the recreation and restarting of each thread, which isn't a very good solution.
I've also tried using the CyclicBarrier's reset() method, but this just seems to cause errors on the existing threads, even when executed after all threads have completed.
My question is:
-Is it possible to 'reset' a barrier and have all the barrier's threads follow the same conditions as they did before the first invocations of await()?
-Or is there another method I should be using to achieve this?
Thanks in advance
The barrier.wait() will suspend the threads. The barrier is already in the main thread, it does not need another. In your algorithm above you show the threads being restarted after displaying stats. You should not need to do this. If the recently awakened threads are in a loop they will go back into the barrier.wait() again.
Following #Totoro's answer, below is a little bit of example code which also incorporates the requirement "I need the threads' run() method to keep looping until a certain condition is met, pausing after every iteration to let all threads synchronise". That makes it complex pretty quick, but hopefully the program output will clarify the example code (or I should just make better examples).
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class BarrierCalc implements Runnable {
public static final int CALC_THREADS = 3;
private static final AtomicBoolean runCondition = new AtomicBoolean();
private static final AtomicBoolean stopRunning = new AtomicBoolean();
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(CALC_THREADS + 1);
for (int i = 0; i < CALC_THREADS; i++) {
new Thread(new BarrierCalc(barrier)).start();
}
try {
runCondition.set(true);
barrier.await();
showln(0, "STATS!");
barrier.await();
showln(0, "start looping 1");
Thread.sleep(200);
runCondition.set(false);
showln(0, "stop looping 1");
barrier.await();
runCondition.set(true);
barrier.await();
showln(0, "start looping 2");
Thread.sleep(100);
runCondition.set(false);
showln(0, "stop looping 2");
barrier.await();
stopRunning.set(true);
showln(0, "finishing");
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
private static final AtomicInteger calcId = new AtomicInteger();
private CyclicBarrier barrier;
private int id;
public BarrierCalc(CyclicBarrier barrier) {
this.barrier = barrier;
id = calcId.incrementAndGet();
}
public void run() {
showln(id, "waiting for start");
try {
barrier.await(); // display stats
barrier.await(); // start running
int loopNumber = 0;
while (!stopRunning.get()) {
showln(id, "looping " + (++loopNumber));
while (runCondition.get()) {
Thread.sleep(10); // simulate looping
}
showln(id, "synchronizing " + loopNumber);
barrier.await();
showln(id, "synchronized " + loopNumber);
// give main thread a chance to set stopCondition and runCondition
barrier.await();
}
showln(id, "finished");
} catch (Exception e) {
e.printStackTrace();
}
}
private static final long START_TIME = System.currentTimeMillis();
public static void showln(int id, String msg) {
System.out.println((System.currentTimeMillis() - START_TIME) + "\t ID " + id + ": " + msg);
}
}
Keep in mind that program output might not be in the order expected: threads that are writing at the same time to one synchronized output (System.out) are given write-access in random order.
You can take a look at my example where I played with CyclicBarrier.Here each worker makes some calculation and at the barrier the condition is checked. If it meets the condition than all workers stop calculations, otherwise they continue:
class Solver {
private static final int REQUIRED_AMOUNT = 100;
private static final int NUMBER_OF_THREADS = 4;
AtomicInteger atomicInteger = new AtomicInteger();
AtomicBoolean continueCalculation = new AtomicBoolean(true);
final CyclicBarrier barrier;
public static void main(String[] args) {
new Solver();
}
class Worker implements Runnable {
int workerId;
Worker(int workerId) {
this.workerId = workerId;
}
public void run() {
try {
while(continueCalculation.get()) {
calculate(workerId);
barrier.await();
}
} catch (Exception ex) {
System.out.println("Finishing " + workerId);
}
}
}
public Solver() {
Runnable barrierAction = () -> {
if (done()) {
continueCalculation.set(false);
}
};
barrier = new CyclicBarrier(NUMBER_OF_THREADS, barrierAction);
List<Thread> threads = new ArrayList(NUMBER_OF_THREADS);
for (int i = 0; i < NUMBER_OF_THREADS; i++) {
Thread thread = new Thread(new Worker(i));
threads.add(thread);
thread.start();
}
}
private void calculate(int workerId) throws InterruptedException {
// Some long-running calculation
Thread.sleep(2000L);
int r = new Random().nextInt(12);
System.out.println("Worker #" + workerId + " added " + r +" = " + atomicInteger.addAndGet(r));
}
private boolean done() {
int currentResult = atomicInteger.get();
boolean collected = currentResult >= REQUIRED_AMOUNT;
System.out.println("=======================================================");
System.out.println("Checking state at the barrier: " + currentResult);
if (collected) {
System.out.println("Required result is reached");
}
System.out.println("=======================================================");
return collected;
}
}

producer - consumer multithreading in Java

I want to write program using multithreading wait and notify methods in Java.
This program has a stack (max-length = 5). Producer generate number forever and put it in the stack, and consumer pick it from stack.
When stack is full producer must wait and when stack is empty consumers must wait.
The problem is that it runs just once, I mean once it produce 5 number it stops but i put run methods in while(true) block to run nonstop able but it doesn't.
Here is what i tried so far.
Producer class:
package trail;
import java.util.Random;
import java.util.Stack;
public class Thread1 implements Runnable {
int result;
Random rand = new Random();
Stack<Integer> A = new Stack<>();
public Thread1(Stack<Integer> A) {
this.A = A;
}
public synchronized void produce()
{
while (A.size() >= 5) {
System.out.println("List is Full");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = rand.nextInt(10);
System.out.println(result + " produced ");
A.push(result);
System.out.println(A);
this.notify();
}
#Override
public void run() {
System.out.println("Producer get started");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
produce();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And the consumer:
package trail;
import java.util.Stack;
public class Thread2 implements Runnable {
Stack<Integer> A = new Stack<>();
public Thread2(Stack<Integer> A) {
this.A = A;
}
public synchronized void consume() {
while (A.isEmpty()) {
System.err.println("List is empty" + A + A.size());
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.err.println(A.pop() + " Consumed " + A);
this.notify();
}
#Override
public void run() {
System.out.println("New consumer get started");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
consume();
}
}
}
and here is the main method:
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
Thread1 thread1 = new Thread1(stack);// p
Thread2 thread2 = new Thread2(stack);// c
Thread A = new Thread(thread1);
Thread B = new Thread(thread2);
Thread C = new Thread(thread2);
A.start();
B.start();
C.start();
}
I think it will be better for understanding and dealing with synchronisation in general if you try to separate three things which are currently mixed:
Task which is going to do the actual job. Names for classes Thread1 & Thread2 are misleading. They are not Thread objects, but they are actually jobs or tasks implementing Runnable interface you are giving to Thread objects.
Thread object itself which you are creating in main
Shared object which encapsulates synchronised operations/logic on a queue, a stack etc. This object will be shared between tasks. And inside this shared object you will take care of add/remove operations (either with synchronized blocks or synchronized methods). Currently (as it was pointed out already), synchronization is done on a task itself (i.e. each task waits and notifies on its own lock and nothing happens). When you separate concerns, i.e. let one class do one thing properly it will eventually become clear where is the problem.
Your consumer and you producer are synchronized on different objects and do not block each other. If this works, I daresay it's accidental.
Read up on java.util.concurrent.BlockingQueue and java.util.concurrent.ArrayBlockingQueue. These provide you with more modern and easier way to implement this pattern.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
You should synchronize on the stack instead of putting it at the method level try this code.
Also don't initalize the stack in your thread classes anyways you are passing them in the constructor from the main class, so no need of that.
Always try to avoid mark any method with synchronized keyword instead of that try to put critical section of code in the synchronized block because the more size of your synchronized area more it will impact on performance.
So, always put only that code into synchronized block that need thread safety.
Producer Code :
public void produce() {
synchronized (A) {
while (A.size() >= 5) {
System.out.println("List is Full");
try {
A.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = rand.nextInt(10);
System.out.println(result + " produced ");
A.push(result);
System.out.println("stack ---"+A);
A.notifyAll();
}
}
Consumer Code :
public void consume() {
synchronized (A) {
while (A.isEmpty()) {
System.err.println("List is empty" + A + A.size());
try {
System.err.println("wait");
A.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.err.println(A.pop() + " Consumed " + A);
A.notifyAll();
}
}
Try this:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CircularArrayQueue<T> {
private volatile Lock rwLock = new ReentrantLock();
private volatile Condition emptyCond = rwLock.newCondition();
private volatile Condition fullCond = rwLock.newCondition();
private final int size;
private final Object[] buffer;
private volatile int front;
private volatile int rare;
/**
* #param size
*/
public CircularArrayQueue(int size) {
this.size = size;
this.buffer = new Object[size];
this.front = -1;
this.rare = -1;
}
public boolean isEmpty(){
return front == -1;
}
public boolean isFull(){
return (front == 0 && rare == size-1) || (front == rare + 1);
}
public void enqueue(T item){
try {
// get a write lock
rwLock.lock();
// if the Q is full, wait the write lock
if(isFull())
fullCond.await();
if(rare == -1){
rare = 0;
front = 0;
} else if(rare == size - 1){
rare = 0;
} else {
rare ++;
}
buffer[rare] = item;
//System.out.println("Added\t: " + item);
// notify the reader
emptyCond.signal();
} catch(InterruptedException e){
e.printStackTrace();
} finally {
// unlock the write lock
rwLock.unlock();
}
}
public T dequeue(){
T item = null;
try{
// get the read lock
rwLock.lock();
// if the Q is empty, wait the read lock
if(isEmpty())
emptyCond.await();
item = (T)buffer[front];
//System.out.println("Deleted\t: " + item);
if(front == rare){
front = rare = -1;
} else if(front == size - 1){
front = 0;
} else {
front ++;
}
// notify the writer
fullCond.signal();
} catch (InterruptedException e){
e.printStackTrace();
} finally{
// unlock read lock
rwLock.unlock();
}
return item;
}
}
You can use Java's awesome java.util.concurrent package and its classes.
You can easily implement the producer consumer problem using the
BlockingQueue. A BlockingQueue already supports operations that wait
for the queue to become non-empty when retrieving an element, and wait
for space to become available in the queue when storing an element.
Without BlockingQueue, every time we put data to queue at the producer
side, we need to check if queue is full, and if full, wait for some
time, check again and continue. Similarly on the consumer side, we
would have to check if queue is empty, and if empty, wait for some
time, check again and continue. However with BlockingQueue we don’t
have to write any extra logic than to just add data from Producer and
poll data from Consumer.
Read more From:
http://javawithswaranga.blogspot.in/2012/05/solving-producer-consumer-problem-in.html
http://www.javajee.com/producer-consumer-problem-in-java-using-blockingqueue
use BlockingQueue,LinkedBlockingQueue this was really simple.
http://developer.android.com/reference/java/util/concurrent/BlockingQueue.html
package javaapplication;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumer {
public static Object lock = new Object();
public static Stack stack = new Stack();
public static void main(String[] args) {
Thread producer = new Thread(new Runnable() {
int i = 0;
#Override
public void run() {
do {
synchronized (lock) {
while (stack.size() >= 5) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
stack.push(++i);
if (stack.size() >= 5) {
System.out.println("Released lock by producer");
lock.notify();
}
}
} while (true);
}
});
Thread consumer = new Thread(new Runnable() {
#Override
public void run() {
do {
synchronized (lock) {
while (stack.empty()) {
try {
lock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(ProdCons1.class.getName()).log(Level.SEVERE, null, ex);
}
}
while(!stack.isEmpty()){
System.out.println("stack : " + stack.pop());
}
lock.notifyAll();
}
} while (true);
}
});
producer.start();
consumer.start();
}
}
Have a look at this code example:
import java.util.concurrent.*;
import java.util.Random;
public class ProducerConsumerMulti {
public static void main(String args[]){
BlockingQueue<Integer> sharedQueue = new LinkedBlockingQueue<Integer>();
Thread prodThread = new Thread(new Producer(sharedQueue,1));
Thread consThread1 = new Thread(new Consumer(sharedQueue,1));
Thread consThread2 = new Thread(new Consumer(sharedQueue,2));
prodThread.start();
consThread1.start();
consThread2.start();
}
}
class Producer implements Runnable {
private final BlockingQueue<Integer> sharedQueue;
private int threadNo;
private Random rng;
public Producer(BlockingQueue<Integer> sharedQueue,int threadNo) {
this.threadNo = threadNo;
this.sharedQueue = sharedQueue;
this.rng = new Random();
}
#Override
public void run() {
while(true){
try {
int number = rng.nextInt(100);
System.out.println("Produced:" + number + ":by thread:"+ threadNo);
sharedQueue.put(number);
Thread.sleep(100);
} catch (Exception err) {
err.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
private final BlockingQueue<Integer> sharedQueue;
private int threadNo;
public Consumer (BlockingQueue<Integer> sharedQueue,int threadNo) {
this.sharedQueue = sharedQueue;
this.threadNo = threadNo;
}
#Override
public void run() {
while(true){
try {
int num = sharedQueue.take();
System.out.println("Consumed: "+ num + ":by thread:"+threadNo);
Thread.sleep(100);
} catch (Exception err) {
err.printStackTrace();
}
}
}
}
Notes:
Started one Producer and two Consumers as per your problem statement
Producer will produce random numbers between 0 to 100 in infinite loop
Consumer will consume these numbers in infinite loop
Both Producer and Consumer share lock free and Thread safe LinkedBlockingQueue which is Thread safe. You can remove wait() and notify() methods if you use these advanced concurrent constructs.
Seems like you skipped something about wait(), notify() and synchronized.
See this example, it should help you.

Facing difficulties in suspending a thread with user input in console

I can suspend the thread with user input in console,but can't resume it again with user input.
I want to resume the thread when user gives input "n". Again it will start with prev state
please help folks.
Thanks.
import java.io.Console;
import java.util.Scanner;
class NewThread implements Runnable {
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
// String username = scanner.nextLine();
try {
for(int i = 5000; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
//String username = scanner.nextLine();
// if(username.equals("y"))
// {
// mysuspend();
// }
synchronized(this) {
while(suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob2 = new NewThread("One");
// System.out.println(username);
try { Scanner scanner = new Scanner(System.in);
String username = scanner.nextLine();
if(username.equals("y"))
{
Thread.interrupted();
// Thread.sleep(10000);
ob2.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(10000);
// ob2.myresume();
System.out.println("Resuming thread One");
}
if(username.equals("n"))
{
ob2.myresume();
}
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Your control flow is wrong.
You are reading input only once. If it is equal to y you are suspending the thread, but then you never go into the if statement that tests for n to resume the thread. I would do it like this:
public class Test {
public static void main(String args[]) {
NewThread ob2 = new NewThread("One");
Scanner scanner = new Scanner(System.in);
while(true) {
String username = scanner.nextLine();
if (username.equals("y")) {
Thread.interrupted();
// Thread.sleep(10000);
ob2.mysuspend();
System.out.println("Suspending thread One");
}
if (username.equals("n")) {
ob2.myresume();
System.out.println("Resuming thread One");
}
if (username.equals("q")) {
ob2.myresume();
break;
}
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
If the user enters "y" the thread will be suspended. If they enter "n" it will be resumed and if they enter "q" you will just break the loop and wait for the thread to finish.
1.. You are using methods wait() and notify() but you want to suspend and resume the thread. So it is not the right way. These methods are used to release any resource (synchronized) from one thread to make it available to some other thread and again give that resource back to same thread.
You should use only suspend() and resume() methods instead.
You cannot use wait() and notify() in your program.
2.. Try doing this in the following manner :
Create two threads. One which will get inputs from user and second which you want to suspend and resume.
According to the input of user call suspend and resume methods on second thread.
*In your code you are getting input from user only once. So once thread suspended is never resumed.

Categories