I was trying to synchronize to two threads, one printing "ping" and another printing "pong", to print something like "ping pong ping pong ping...." I wrote the following program to achieve this, but couldn't get the expected result. I wonder what mistake I'm making. Solutions for the same are available on the internet but I thought I should give it a try myself before looking for a readily available answer.
class MyThread implements Runnable{
String val = null;
MyThread(String val) {
this.val = val;
}
public void run() {
while(true){
PingPong.pintMessage(val);
}
}
}
public class PingPong {
static Integer turn = 1;
public static void main(String args []) {
Thread t1 = new Thread(new MyThread("ping"));
Thread t2 = new Thread(new MyThread("pong"));
t1.start();
t2.start();
}
public static void pintMessage(String msg) {
synchronized (turn) {
if(turn==1) {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn=2;
}
else {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn = 1;
}
}
}
}
Output :
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Kindly advise what fundamental mistake I'm making here and if there is a better approach to achieve the same behaviour. Thanks !!
After making suggested changes : I have tried to use thread communication using wait/notify but getting IllegalMonitorStateException. I guess I have used wait/notify on the object I am acquiring lock on(wait/notify used in synchronized context). Please help me understand the subtlety of the concept. Thnaks !
class MyThread implements Runnable{
String val = null;
MyThread(String val) {
this.val = val;
}
public void run() {
while(true){
try {
PingPong.printMessage(val);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class PingPong {
static Integer turn = 1;
public static void main(String args []) {
Thread t1 = new Thread(new MyThread("ping"));
Thread t2 = new Thread(new MyThread("pong"));
t1.start();
t2.start();
}
public static void printMessage(String msg) throws InterruptedException {
synchronized (turn) {
if(turn==1) {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn=2;
}
else {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn = 1;
}
turn.notifyAll();
turn.wait();
}
}
}
Output :
Thread-0 ping
Exception in thread "Thread-0" Thread-1 pong
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at PingPong.printMessage(PingPong.java:40)
at MyThread.run(PingPong.java:12)
at java.lang.Thread.run(Unknown Source)