how to decide the looping condition for wait() in Java - java

I am understanding wait() in Java in regards to multithreaded, and as per the documentation, wait() should always be in a loop.
I have difficult in understanding what is the condition we have to give in the loop. Typically, I have seen:
synchornized(obj) {
while(some_condition) {
obj.wait();
}
// some other code
}
I am having difficulty in understanding the "condition" which is used in the loop within which we are keeping wait().
I tried to implement a scenario in which I created two different threads (two different classes implementing Runnable interface), for printing Odd and Even numbers, like: 1 ,2 ,3,4,5,6...
As this is inter-thread communication and we need synchronization, I am having difficulty in relating what is the condition on which I have to keep wait() in loop for these two different threads.
Any clues as to how to decipher this (the condition we keep in loop) greatly appreciated.

Here, maybe this few lines will push you in the right direction, as a follow up to my previous comments.
class LastPrintedMonitor {
public boolean wasLastEven = false;
}
class PrinterOdd implements Runnable {
LastPrintedMonitor monitor;
public PrinterOdd(LastPrintedMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
for (int i = 2; i < 40; i += 2) {
synchronized (monitor) {
while (!monitor.wasLastEven) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
monitor.wasLastEven = false;
monitor.notifyAll();
}
}
}
}
class PrinterEven implements Runnable {
LastPrintedMonitor monitor;
public PrinterEven(LastPrintedMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
for (int i = 1; i < 40; i += 2) {
synchronized (monitor) {
while (monitor.wasLastEven) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
monitor.wasLastEven = true;
monitor.notifyAll();
}
}
}
}
public class EvenOddPrinterDemo {
public static void main(String[] args) {
LastPrintedMonitor monitor = new LastPrintedMonitor();
Thread odd = new Thread(new PrinterOdd(monitor));
Thread even = new Thread(new PrinterEven(monitor));
odd.start();
even.start();
try {
odd.join();
even.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Done!");
}
}
You mentioned two classes so their synchronized methods will not be synchronized to each other. That's why we synchronized on monitor, as there has to be something that those two objects share to make them "hear" each other.

The looping condition should check whether the execution(threads of the current class) need to be temporarily paused.
Taking an example of famous producer-consumer problem, where in the producer will somehow looks like
synchronized(mySharedObj)
{
while(mySharedObj.length==maxSize)
{
mySharedObj.wait();
}
}
If there are n number of Producer Threads on mySharedObj, all will be waiting when the shared resource(mySharedObj) has reached its limit.

Related

Java Threads: How to print alphabets and numbers using two threads one at a time

I am trying to work around with threads in java. Though I understand that threads output are unpredictable, However was wondering if there is a way to do that.
I have to implement two threads, one prints alphabets(a,b,c...z) and other prints numbers(1,2,3....26). Have to implement it in such a way that the output should be a,1,b,2,c,3,d,4......z,26. Below is my code but it doesn't give the desired output.
public class ThreadsExample {
public static void main(String[] args) {
Runnable r = new Runnable1();
Thread t = new Thread(r);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}
class Runnable2 implements Runnable{
public void run(){
for(char i='a';i<='z';i++) {
System.out.print(i+",");
}
}
}
class Runnable1 implements Runnable{
public void run(){
for(int i=1;i<=26;i++) {
System.out.print(i+",");
}
}
}
What tweak should I make in the code to get the desired output? How does synchronization helps here? Or is it really possible when working with Threads at all?
PS: This is not an assignment or some exercise. Its self learning.
It is possible. You need to synchronize it well.
Approach Pseudocode
query some (synchronized) state
state will tell whether nums or chars are allowed
if state allows char and caller will put chars, do it now and change state and wake up waiting threads
if not, wait
if state allows numbers and caller will put numbers, do it now and change state and wake up waiting threads
if not, wait
Java code
public class ThreadsExample {
public static ThreadsExample output = new ThreadsExample ();
public static void main(String[] args) {
Runnable r = new Runnable1();
Thread t = new Thread(r);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
private Object syncher = new Object (); // we use an explicit synch Object, you could use annotation on methods, too. like ABHISHEK did.
// explicit allows to deal with more complex situations, especially you could have more the one locking Object
private int state = 0; // 0 allows chars, 1 allows ints
public void print (char pChar) {
synchronized (syncher) { // prevent the other print to access state
while (true) {
if (state == 0) { // char are allowed
System.out.print(pChar + ","); // print it
state = 1; // now allow ints
syncher.notify(); // wake up all waiting threads
return;
} else { // not allowed for now
try {
syncher.wait(); // wait on wake up
} catch (InterruptedException e) {
}
}
}
}
}
public void print (int pInt) {
synchronized (syncher) {
while (true) {
if (state == 1) {
System.out.print(pInt + ",");
state = 0;
syncher.notify();
return;
} else {
try {
syncher.wait();
} catch (InterruptedException e) {
}
}
}
}
}
}
class Runnable2 implements Runnable{
public void run(){
for(char i='a';i<='z';i++) {
ThreadsExample.output.print(i);
}
}
}
class Runnable1 implements Runnable{
public void run(){
for(int i=1;i<=26;i++) {
ThreadsExample.output.print(i);
}
}
}
Output
a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8,i,9,j,10,k,11,l,12,m,13,n,14,o,15,p,16,q,17,r,18,s,19,t,20,u,21,v,22,w,23,x,24,y,25,z,26,
The whole idea of threads: it represents a "stream of activity" that executes code independent of other threads.
In your case, you want that these two threads go in "lockstep". Thread A does one step, then Thread B, then A, then B.
In order to get there, the two threads need something "synchronize" on - in other words: A sends a signal to B when it has done its steps - and B has to wait for that signal. Then B does its thing, signals to A, ...
For starters, a simple boolean value would do. One thread sets it to true, the other to false (to indicate when it has made its step). Then the thread waits for the boolean to toggle again.
As you intend to learn things, I would just start experimenting from there. In case you want to take detours, look here for example. This might help as well.
HERE IS THE CODE::
You need to create 2 threads and implement wait and notify methods correctly you can also refer "Create two threads, one display odd & other even numbers" for your answer.
public class ThreadClass {
volatile int i = 1;
volatile Character c = 'a';
volatile boolean state = true;
synchronized public void printAlphabet() {
try {
while (!state) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " +c);
state = false;
c++;
notifyAll();
}
synchronized public void printNumbers() {
try {
while (state) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + i);
state = true;
i++;
notifyAll();
}
public static void main(String[] args) {
ThreadClass threadClass = new ThreadClass();
Thread t1 = new Thread() {
int k = 0;
#Override
public void run() {
while (k < 26) {
threadClass.printAlphabet();
k++;
}
}
};
t1.setName("Thread1");
Thread t2 = new Thread() {
int j = 0;
#Override
public void run() {
while (j < 26) {
threadClass.printNumbers();
j++;
}
}
};
t2.setName("Thread2");
t1.start();
t2.start();
}
}
Your threads are running at the same time. But not the way you want it, as mentioned above. You will see blocks of data from thread 1 and then a block of data from thread 2; and this is because of thread scheduling. Thread 1 is just queuing its output before thread 2.
To test this theory, increase your output to a 1000 records for example as the alphabet and 26 numbers are not as large to see this.
By doing so, you will see these 'blocks' of data. There is a way to do what you mentioned, but it is not advisable as this is not demonstrating how threads actually work but rather you forcing it to work that way.
With less Code:
class MyRunnable implements Runnable {
private static int n = 1;
private static char c = 'a';
public void run() {
for (int i = 1; i <= 26; i++) {
synchronized (this) {
try {
notifyAll();
if (Thread.currentThread().getName().equals("A")) {
System.out.print(c + ",");
c++;
} else {
System.out.print(n + ",");
n++;
}
if (i != 26) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class PrintAlphabetNumberJob {
public static void main(String[] args) throws InterruptedException {
MyRunnable r = new MyRunnable();
Thread tAlphabet = new Thread(r, "A");
Thread tNumber = new Thread(r, "N");
tAlphabet.start();
Thread.sleep(100);
tNumber.start();
}
}

Do not synchronize on objects that may be reused [duplicate]

public class Alternate {
static Boolean mutex = true;
public static void main(String[] args) {
Thread t1 = new Thread(new Odd(mutex));
Thread t2 = new Thread(new Even(mutex));
t1.start();
t2.start();
}
}
class Odd implements Runnable{
Boolean mutex;
Odd( Boolean mutex){
this.mutex=mutex;
}
#Override
public void run() {
try {
synchronized(mutex){
while(mutex){
mutex.wait();
}
System.out.println("odd");
mutex=true;
mutex.notifyAll();
Thread.sleep(500);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Even implements Runnable{
Boolean mutex;
Even( Boolean mutex){
this.mutex=mutex;
}
#Override
public void run() {
try {
synchronized(mutex){
while(!mutex){
mutex.wait();
}
System.out.println("even");
mutex=false;
mutex.notifyAll();
Thread.sleep(500);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The error is
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at com.test.concurrency.Even.run(Alternate.java:55)
at java.lang.Thread.run(Thread.java:722)
I am not able to figure out the reason for the error. I am calling notifyAll() from synchronised context and calling it from the correct object.
You're changing the lock out from under your threads. Every time you set your boolean to something, that's a different object; the code
mutex=true;
mutex.notifyAll();
sets mutex to a different object from the one the thread synchronized on (so the thread hasn't acquired the monitor for it), then it calls notifyAll on the new object.
Use a single lock and don't change it.
Locking on Booleans, numeric wrappers, or Strings is too error-prone and should be avoided. Not only can you end up with the error you're seeing, but other unrelated parts of the application (maybe written by somebody else following the same practice) could be locking on the same object and causing mysterious problems. Booleans, number wrappers, and strings are available to everything in the JVM. It's better to use a lock that is constrained in scope so that nothing else in your application can acquire it.
Often it's best to use a dedicated lock, something you don't use for any other purpose. Overloading something with different uses can cause trouble too easily.
Corrected Code if anyone needs
import java.util.concurrent.atomic.AtomicInteger;
public class Alternate {
static final AtomicInteger mutex = new AtomicInteger(0);
public static void main(String[] args) {
Thread t1 = new Thread(new Odd());
Thread t2 = new Thread(new Even());
t1.start();
t2.start();
}
static class Odd implements Runnable{
#Override
public void run() {
try {
for(int i=0;i<10;i++){
synchronized(mutex){
while(mutex.get()==1){
mutex.wait();
}
System.out.println("odd");
mutex.compareAndSet(0, 1);
mutex.notifyAll();
}
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Even implements Runnable{
#Override
public void run() {
try {
for(int i=0;i<10;i++){
synchronized(mutex){
while(mutex.get()==0){
mutex.wait();
}
System.out.println("even");
mutex.compareAndSet(1, 0);
mutex.notifyAll();
}
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Java Interlocked Threads

I'm getting interlocked threads in somewhat simple producer/consumer (and based on examples correct) code.
There is a thread executing this:
public void append(final Object obj) {
buffer.add(obj);
if (buffer.size() >= BUFFER_MAX_SIZE) {
insertLock.lock();
switchLock.lock();
insertLock.unlock();
bufferFull.signal();
try {
bufferSwitch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
switchLock.unlock();
}
}
There is another thread with this code:
try {
insertLock.lock();
while (true) {
switchLock.lock();
insertLock.unlock();
bufferFull.await();
switchBuffers();
bufferSwitch.signal();
insertLock.lock();
switchLock.unlock();
if (insertBuffer.size() > 0) {
db.insert(insertBuffer);
insertBuffer.clear();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
As I mentioned it is based on the producer/consumer example on the Condition API documentation. I can't detect why both threads get stuck on the conditions await method.
Is there any error ? Looks like there is something my naked eyes can't see.
Thank you,
PS: Added working code.
Thread A does
insertLock.lock();
switchLock.lock();
and Thread B does
switchLock.lock();
....
insertLock.lock();
So if Thread A acquires insertLock while B gets switchLock, neither A nor B can proceed to the next line.
It's a clasic deadlock situation. You should always make sure the locks are getting locked in the same order.
For a producer/consumer problem with threads you could look at the BlockingQueue interface and its derived classes that java offers.
For example:
package cl.mds.migracion;
import java.util.concurrent.ArrayBlockingQueue;
public class Example {
static ArrayBlockingQueue<String> buffer = new ArrayBlockingQueue<String>(5);
static class Producer implements Runnable{
#Override
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(500); //seleep 500ms to simulate producer time
buffer.put(String.valueOf(i)); //put waits the thread until there is size in the queue.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable{
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(100); //seleep 100ms to simulate slower consumer tha producer
System.out.printf("Consuming %s ....%n",buffer.take()); //take waits the thread until there is something in the queue
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
System.out.printf("Starting producer/consumer ....%n");
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
System.out.printf("Finishing ....%n");
}
}

Notify not getting the thread out of wait state

I am trying to use 2 threads. 1 thread prints only odd number and the other thread prints only even number and It has to be an alternative operation.
Eg:
Thread1 1
Thread2 2
Thread1 3
Thread2 4
and so on..
Below is the program, please let me know where I am going wrong as the thread1 is not coming out of wait state even when the thread2 is notifying it..
public class ThreadInteraction {
public static void main(String[] args) {
new ThreadInteraction().test();
}
private void test() {
ThreadA ta = new ThreadA();
Thread t = new Thread(ta);
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i=2;i<=50;){
System.out.println("Thread2 "+i);
synchronized (t) {
try {
t.notify();
t.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
class ThreadA implements Runnable{
#Override
public void run() {
for(int i=1;i<50;){
System.out.println("Thread1 "+i);
synchronized (this) {
try {
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
Problem is that in one case you are taking lock on Thread t [synchronized (t) ] while in other case you are taking lock on TheadA object itself [synchronized(this)].
If you want threads to talk to each other then both should take lock on same object only then wait notify will work as you expect.
Edit:
There is another problem in your program, you are not using any variable to coordinate between 2 threads. SO you may see output like this 2,1,4,3...so on. Point is threads will work alternately but not in sequence.
So you should share a single variable between 2 threads which should be incremented.
Second issue is you are not taking care of spurious wake up calls [read some docs on this], you should always have wait called inside a while loop.
Modified my code based on the answer provided by Lokesh
public class ThreadInteraction {
public static void main(String[] args) {
new ThreadInteraction().test();
}
private void test() {
ThreadA ta = new ThreadA();
Thread t = new Thread(ta);
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i=2;i<=50;){
System.out.println("Thread2 "+i);
synchronized (ta) {
try {
ta.notify();
ta.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
class ThreadA implements Runnable{
#Override
public void run() {
for(int i=1;i<50;){
System.out.println("Thread1 "+i);
synchronized (this) {
try {
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
You have a real confusion of threads and locks. I suggest you create one and only one object to use for locking to start with as you don't appear to have a clear idea what you are locking.
If you notify() and nothing is listening, the signal is lost. However, a wait() can wake spuriously.
For this reason, a notify() should be accompanied by a state change and a wait() should be in a loop checking that change.

Java Threads: Wait Notify mechanism with ArrayList

I tried implementing wait/notify mechanism to modify the ArrayList using two separate threads.
It seems to work fine for first iteration but then for second iteration it waits forever in addToArray() method. I am not able to figure out why is it waiting forever in the method? As per my understanding the other thread (removing an item) should pick up when other thread goes to wait.
Please have a look and point out possible bug if any. I know I can use Vector to have thread-safe operation but that is not what I want.
package threadTest;
import java.util.*;
public class DhagaJava {
public static void main(String...strings){
ArrayModification am = new ArrayModification();
Thread t1 = new Thread(new AddToArray(am));
Thread t2 = new Thread(new RemoveFromArray(am));
t1.start();
t2.start();
}
}
class ArrayModification{
boolean added = false;
ArrayList<Integer> al;
ArrayModification(){
al = new ArrayList<Integer>();
}
public synchronized void addToArrayList(int x) {
if (added == true){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.al.add(x);
System.out.println(al);
System.out.println("Added!! :)");
added = true;
notifyAll();
}
public synchronized void removeFromList(){
if( added== false){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(al);
this.al.remove(0);
System.out.println("Removed!! :' ");
added = false;
notifyAll();
}
}
class AddToArray implements Runnable{
ArrayModification ma;
AddToArray(ArrayModification m){
this.ma = m;
}
public void run() {
for (int i = 0; i<10; i++)
ma.addToArrayList(i);
}
}
class RemoveFromArray implements Runnable{
ArrayModification ma;
RemoveFromArray(ArrayModification a){
this.ma = a;
}
public void run(){
ma.removeFromList();
}
}
class RemoveFromArray implements Runnable{
ArrayModification ma;
RemoveFromArray(ArrayModification a){
this.ma = a;
}
public void run(){
//for(int j=11;j<20; j++)
ma.removeFromList();
}
}
Output is:
[0]
Added!! :)
[0]
Removed!! :'
[1]
Added!! :)
Only problem you have is the removeFromList runs only once (because you commended out the for loop). That’s the reason why there is no second remove in the log and that addToArrayList starts waiting forever (waits for someone remove the item from the list).
I tried your code after removing the comment and works fine!
Rather than re-invent the wheel, just use a CopyOnWriteArrayList. It comes with concurrency out of the box.
Your notifyAll is inside the synchronized block. So the other thread may be awaken before he can act. So it may be blocked.
I'm not sure I understood your goal, but this construction could be better :
public void addToArrayList(int x) {
synchonized(this.al) {
if (added == true){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.al.add(x);
System.out.println(al);
System.out.println("Added!! :)");
added = true;
}
notifyAll();
}
But this is very complex. Do you have a more general goal ? Maybe a task queue with only one thread could suit you better : it would be faster, lighter, simpler, and as parallelized (that is not at all).

Categories