I am trying to print even and odd using two separate threads which communicate with each other by wait and notify.
I do know that i refers to Integer object which is in heap. hence changes made by one thread should be visible to both thread. Also I am using volatile keyword for declaration of Integet i.
I cant seem to understand how value of variable i is shown as 1 even after it has been incremented.
The output of code is
Even Thread got lock i=1
Even Thread waiting.. i=1
Odd Thread got lock i=1
Odd Thread : i=2
Odd Thread Run called NotifyAll
Odd Thread got lock i=2
Odd Thread waiting.. i=2
Even Thread woken up.. i=1
Even Thread waiting.. i=1
package programs;
public class EvenOdd {
static Object lck = new Object();
volatile static Integer i=1;
volatile static Integer N = 1000;
public static void main(String args[]){
EvenRunner e = new EvenRunner(lck, i, N);
OddRunner o = new OddRunner(lck, i, N);
Thread t1 = new Thread(e,"Even Thread ");
Thread t2 = new Thread(o,"Odd Thread ");
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch(InterruptedException ex) {
System.out.println("Interrupted : "+ex);
}
}
}
class EvenRunner implements Runnable{
Object lck;
Integer i;
Integer N;
EvenRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
#Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Even Thread got lock i="+i);
while(i%2==1){
try {
System.out.println(" Even Thread waiting.. i="+i);
lck.wait();
System.out.println(" Even Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Even Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
class OddRunner implements Runnable{
Object lck;
Integer i;
Integer N;
OddRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
#Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Odd Thread got lock i="+i);
while(i%2==0){
try {
System.out.println(" Odd Thread waiting.. i="+i);
lck.wait();
System.out.println(" Odd Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Odd Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
Expected Result: should be that other thread should also see the value of variable I as 2 after it has been incremented.
Actual result: value of variable i is read as 1 by other thread even after incrementing it.
Expected output should be that other thread should also see the value of variable I as 2 after it has been incremented.
When you construct evenRunner and oddRunner, you're copying the same Integer reference into each class as an instance field.
But Integer is immutable - when you execute ++i; that changes the field to refer to a different Integer object. It doesn't modify the content of the existing integer object... so your two threads are operating on entirely separate fields, and won't interact at all.
If you want to have a single object that both threads can modify, use AtomicInteger instead.
Related
I am trying to print even odd numbers using two threads with interrupt method.
I refereed code from internet and wrote a code showing below.It prints properly but after prints 20,program is continuing it's execution.
What change do i have to make in the code to stop the execution of the program?
Without oldNum check code is working fine. Is there any logic to provide oldNum check ?
If I remove Thread.sleep(1000L) from Line-a then it only prints "Even Thread prints 20" and continue execution.What is happening here?
Provided break points inside run() method and inside for loop of main method ,run() methods break points are not hitting.Why this is happening?
In short I want to know what is the code flow here.
Thanks
Vikash
public class PrintOddEvenUsingInterrupt {
public static volatile int count;
public static void main(String[] args) throws InterruptedException {
Thread oddThread = new Thread(new OddInterruptThread(), "Odd Thread ");
Thread evenThread = new Thread(new EvenInterruptThread(),"Even Thread ");
oddThread.start();
evenThread.start();
for (int i = 0; i < 20; i++) {
count++;
oddThread.interrupt();//Break points works here
evenThread.interrupt();
Thread.sleep(1000L);// Line-a
}
}
static class OddInterruptThread implements Runnable {
public void run() {
int oldNum = 0;//Break points doesn't works here
while (true) {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
}
if (oldNum != count && count % 2 == 1) {
System.out.println(Thread.currentThread().getName()
+ " prints " + count);
oldNum = count;
}
}
}
}
static class EvenInterruptThread implements Runnable {
public void run() {
int oldNum = 0;//Break points doesn't works here
while (true) {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
}
if (oldNum != count && count % 2 == 0) {
System.out.println(Thread.currentThread().getName()
+ " prints " + count);
oldNum = count;
}
}
}
}
}
The reason your program is not stopping is: while your main thread exits, your odd and even threads sleeps in infinite loop.
You will need to define a stopping condition for your threads to come out.
One way to achieve this is via using conditions.
Eg:
public volatile static boolean oddFinished = false;
public volatile static boolean evenFinished = false;
Then in your threads, instead of looping infinitely, loop against condition
while (! oddFinished){
// also change your thread sleep to sleep for fewer time interval (say 1000L or whatever your program wants to wait for)
}
Do the same for even thread...
while (! evenFinished){
// also change your thread sleep to sleep for fewer time interval (say 1000L or whatever your program wants to wait for)
}
And in the main thread, you can add the following code after your for loop ends...
oddFinished = true;
evenFinished = true;
oddThread.join();
evenThread.join();
This will allow your code to stop gracefully.
I think the simplest solution will be to make your threads demons.
Just add the following lines before starting your thteads.
oddThread.setDaemon(true);
evenThread.setDaemon(true);
And your program will exit immediately after exiting from main.
Synchronization works correctly in this code:
class PrintNumbers {
synchronized public void display() {
System.out.println("in display");
for (int i = 0; i < 3; i++) {
System.out.println("Thread name : "+ Thread.currentThread().getName() + " i= " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.getMessage();
}
}
System.out.println("out of display");
}
}
class MyThread implements Runnable {
Thread t;
PrintNumbers printNumbers;
MyThread(PrintNumbers printNumbers, String s) {
this.printNumbers = printNumbers;
t = new Thread(this,s);
t.start();
}
public void run() {
printNumbers.display();
}
}
class SyncExample {
public static void main(String[] args) {
PrintNumbers printNumbers = new PrintNumbers();
new MyThread(printNumbers, "My Thread 1");
new MyThread(printNumbers, "My Thread 2");
}
}
Output:
in display
Thread name : My Thread 1 i= 0
Thread name : My Thread 1 i= 1
Thread name : My Thread 1 i= 2
out of display
in display
Thread name : My Thread 2 i= 0
Thread name : My Thread 2 i= 1
Thread name : My Thread 2 i= 2
out of display
but not in this code:
class PrintNumbers {
synchronized public void display() {
System.out.println("in display");
for (int i = 0; i < 3; i++) {
System.out.println("Thread name : "+ Thread.currentThread().getName() + " i= " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.getMessage();
}
}
System.out.println("out of display");
}
}
class MyThread implements Runnable {
Thread t;
PrintNumbers printNumbers;
MyThread(String s) {
this.printNumbers = new PrintNumbers();
t = new Thread(this,s);
t.start();
}
public void run() {
printNumbers.display();
}
}
class SyncExample {
public static void main(String[] args) {
new MyThread("My Thread 1");
new MyThread("My Thread 2");
}
}
Output:
in display
Thread name : My Thread 1 i= 0
in display
Thread name : My Thread 2 i= 0
Thread name : My Thread 1 i= 1
Thread name : My Thread 2 i= 1
Thread name : My Thread 2 i= 2
Thread name : My Thread 1 i= 2
out of display
out of display
I cannot understand what difference wrt Synchronization does it make to initialize PrintNumbers in the Runnable MyThread and in the SyncExample class. Please explain.
I cannot understand what difference wrt Synchronization does it make to initialize PrintNumbers in the Runnable MyThread and in the SyncExample class.
It doesn't. What does matter is that in your first example, you have only one PrintNumbers instance which both threads share. But in your second example, you have two separate PrintNumbers instances, one for each thread.
Since PrintNumbers#display synchronizes on the instance (synchronized instance methods synchronize on this), it only synchronizes within the instance, not across multiple instances.
When both threads share an instance, the two calls to display are serialized. But when the threads each have their own instance, the two calls to display are on separate instances, and thus there is no serialization of the calls, they can overlap.
Because in the second code each thread has its own PrintNumbers object so they work in parallel. In the first one they share the single PrintNumbers object and work with it in synchronized way.
PS.
Remember that synchronized for non-static methods makes synchronization on object (for static methods on class).
It is working in both cases as it should. The difference is that in the first case you have a single object that is synchronized. In to second one you have two. They both are called only once so they are synchronized perfectly.
synchronized doesn't work between objects, only within one.
When I execute the following piece of code
public class ThreadTalk {
public static void main(String[] args) {
SimpleThread obj = new SimpleThread();
Thread t = new Thread(obj, "NewThread");
t.start();
synchronized (obj) {
System.out.println("In Synchronized BLOCK");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Out of Synchronized BLOCK");
}
}
}
class SimpleThread implements Runnable {
public void run() {
System.out.println("The thread running now " + Thread.currentThread());
for (int i = 0; i < 10; i++) {
System.out.println("The val of i= " + i);
}
}
}
The output that I am getting is
In Synchronized BLOCK
The thread running now Thread[NewThread,5,main]
The val of i= 0
The val of i= 1
The val of i= 2
The val of i= 3
The val of i= 4
The val of i= 5
The val of i= 6
The val of i= 7
The val of i= 8
The val of i= 9
Out of Synchronized BLOCK
where as I am expecting an output like
In Synchronized BLOCK
Out of Synchronized BLOCK
The thread running now Thread[NewThread,5,main]
The val of i= 0
The val of i= 1
The val of i= 2
The val of i= 3
The val of i= 4
The val of i= 5
The val of i= 6
The val of i= 7
The val of i= 8
The val of i= 9
If I am putting a Lock on the SimpleThread object using the Synchronized block of main thread, how is my NewThread running when main thread is going to sleep.I mean shouldn't the NewThread wait till the Main thread has removed the lock on the SimpleThread object, as both threads are running on the same object.
run() and/or start() do not take any locks. They just run code. You need to actually have SimpleTread take the same lock as the main thread for those two threads to synchronize in some fashion.
Rather than try to synchronize on the the Runnable object, I think best practice would be to explicitly declare a separate object to use as a lock.
class ThreadTalk{
public static void main(String[] args){
Object lock = new Object();
SimpleThread obj=new SimpleThread( lock );
Thread t=new Thread(obj,"NewThread");
t.start();
synchronized(lock){
System.out.println("In Synchronized BLOCK");
try{
Thread.sleep(5000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Out of Synchronized BLOCK");
}
}
}
class SimpleThread implements Runnable{
private final Object lock;
public SimpleThread( Object lock ) { this.lock = lock;}
public void run(){
synchronized( lock ) {
System.out.println("The thread running now "+Thread.currentThread());
for(int i=0;i<10;i++){
System.out.println("The val of i= "+i);
}
}
}
}
synchronized block does not do what you think. It means that only one thread can be inside of it (or rather inside any synchronized block on the same object) at the same time. In your case, there is only one (main) thread inside the block. The other one is executing different code. That is expected.
You need to synchronize in both threads on the same object (the so-called "monitor") to make them mutually exclusive.
The simplest way to do that is to make the run() method itself synchronized:
class SimpleThread implements Runnable {
// See the synchronized modifier on the next line
public synchronized void run() {
System.out.println("The thread running now " + Thread.currentThread());
for (int i = 0; i < 10; i++) {
System.out.println("The val of i= " + i);
}
}
}
You would also need to make sure that you synchronize on the SimpleThread object before you start it in a Thread, so you need to move the t.start(); statement inside the synchronized (obj) { block. If you don't do that, the two threads are still improperly synchronized, and there's no telling which thread will run first.
I have a Thread Object - ThreadB which add numbers 1 - 100. I create 2 instances of it - b & c.
Start the 2 threads(different instances) and run it.
Result:
Waiting for b to complete...
Total is: 4950
Waiting for c to complete...
Why does my second instance does not complete...
Java code:
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
ThreadB c = new ThreadB();
b.start();
c.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
synchronized(c){
try{
System.out.println("Waiting for c to complete...");
c.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + c.total);
}
}
}
class ThreadB extends Thread{
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
Because your second ThreadB finishes while you're in the block synchronized on the first ThreadB. You then wait on your second ThreadB, but the notify() has already happened so you'll wait there forever.
Note that this isn't guaranteed, and your program will probably work sometimes.
Put some print statements inside your ThreadB class to test this theory.
If you just wish to wait for both threads to complete you should use the Thread join method, which is specifically designed for this.
It also makes use of wait and notify (or rather notifyAll) underneath the hood.
Your code will be much cleaner too:
System.out.println("Waiting for b to complete...");
b.join();
System.out.println("b completed.");
System.out.println("Waiting for c to complete...");
c.join();
System.out.println("c completed.");
System.out.println("b's total is " + b.total");
System.out.println("c's total is " + c.total");
This is not the right way to approach the problem. You are trying to serialize two independent threads, which is pointless.
If your only purpose is to give the user some feedback, you make each thread inform the user that it terminated its job before quitting:
class ThreadB extends Thread{
String name;
int total;
public ThreadB(String name){
this.name = name;
}
#Override
public void run(){
System.out.println("Waiting for "+name+" to complete...");
for(int i=0; i<100 ; i++){
total += i;
}
System.out.println(name+" completed. Total is "+total);
}
}
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB("b");
ThreadB c = new ThreadB("c");
b.start();
c.start();
}
}
Otherwise, if you need to do something after all threads have finished, you synchronize on a shared object, not on a thread.
I made this sample to test wait/notify functionalities:
public class WaitingTest implements Runnable {
Thread b = new Thread(this,"query");
int total=0;
public static void main(String[] args){
WaitingTest w = new WaitingTest();
}
public WaitingTest(){
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait(10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + total);
}
}
#Override
public void run(){
synchronized(b){
for(int i=0; i<1000000000 ; i++){
total += i;
}
}
}
}
The problem is, my output should be zero since Im notifying the wait after 10ms and my thread takes longer than this to execute its work. So, my output should be zero, instead its coming another value. What am I missing?
EDIT:
public class WaitingTest implements Runnable {
Thread b = new Thread(this,"query");
int total=0;
public static void main(String[] args){
WaitingTest w = new WaitingTest();
}
public WaitingTest(){
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + total);
}
}
#Override
public void run(){
synchronized(b){
b.notify();
for(long i=0; i<100000 ; i++){
total += i;
}
}
}
}
The javadoc for wait() states
This method causes the current thread (call it T) to place itself in
the wait set for this object and then to relinquish any and all
synchronization claims on this object
So when you do
b.wait(10);
the current thread releases the synchronized it has on b and your other thread can therefore acquire it in the run() method coming from
b.start();
The total starts increasing. When 10ms is up, the main thread reacquires the lock on b (assuming the run() completes) and prints out the total. Note that your total will most likely overflow.
You get overflow (you cannot sum up these 1000000000 non-negative ints and store the result in an int). Define total as long. Also call b.notify() or b.notifyAll() after your loop in the run method is done.
Also, change wait(10) to just wait(), this will make the printing thread wait for
the calculating thread as much as needed (and not just for 10 milliseconds).
This is the proper way of doing this test.
Regarding the thread syncing part I suggest you read something e.g. these old articles.
http://www.javaworld.com/article/2074217/java-concurrency/java-101--understanding-java-threads--part-1--introducing-threads-and-runnables.html
http://www.javaworld.com/article/2074318/java-concurrency/java-101--understanding-java-threads--part-2--thread-synchronization.html
http://www.javaworld.com/article/2071214/java-concurrency/java-101--understanding-java-threads--part-3--thread-scheduling-and-wait-notify.html
http://www.javaworld.com/article/2074481/java-concurrency/java-101--understanding-java-threads--part-4---thread-groups--volatility--and-threa.html