Solved

java thread methods wait(), notify(), join()

Posted on 2014-02-11
13
842 Views
Last Modified: 2014-03-25
Hi,

I would like to know what are the practical uses of java thread methods wait(), notify(), join() etc.

When to use each one.

Does Synchronized method block always needs to contain wait() method inside that. Is there is a case of Synchronized method block  without wait() method.
please advise
Any links resources ideas highly appreciated. Thanks in advance
0
Comment
Question by:gudii9
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
13 Comments
 
LVL 35

Expert Comment

by:mccarl
ID: 39851830
I would like to know what are the practical uses of java thread methods wait(), notify(), join() etc.

When to use each one.
I'm pretty sure this has been covered (at length) in all your other questions on this topic. At a basic level, they are needed anywhere where multiple threads need to co-ordinate their execution with each other. Therefore, there many uses for these and we aren't really going to be able to give you more than what you have already found in the example tutorials that you have posted links to, and in the code that various experts have posted in your questions.

Does Synchronized method block always needs to contain wait() method inside that. Is there is a case of Synchronized method block  without wait() method.
No, a synchronized block will not alwyas contain a wait() method. Synchronized blocks/methods are totally different to wait()/notify(). Yes they both are concerned with co-ordinating execution between multiple threads but they work on totally different principles and are used for different purposes. Sometimes they appear together in the same code but this is just dependant on the purpose of the code.
0
 
LVL 7

Author Comment

by:gudii9
ID: 39857366
No, a synchronized block will not alwyas contain a wait() method

Can you please point me to some example or link where they are not together?

Please advise
0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39859658
Here is an example of a synchronize with no wait method.

This is the main controller program... it will create 3 things.  1 of those objects is going to be called a "Counter".  The other 2 objects are going to be called ThreadExamples.

What the main class will do is create 1 instance of a counter, and 2 instances of ThreadExamples.

Each ThreadExample will be constructed using the same exact "Counter" object.

package ee.com;

public class MyExample {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Counter myCounter = new Counter();
		
		ThreadExample firstThread = new ThreadExample(myCounter,"firstThread");
		ThreadExample secondThread = new ThreadExample(myCounter,"secondThread");
		
		firstThread.start();
		secondThread.start();
		
	}

}

Open in new window


Here is the code for the new Counter Class:

The counter class is very basic.  It just contains an integer called count.... and getter/setter methods  to get and set count.

It also contains a method to increment the count called addToCount.   addToCount is synchronized so that we don't have more than 1 thread try to increment the count at the same time.

package ee.com;

public class Counter {

	private int count;
	
	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public synchronized void addToCount() {
		this.count++;
		
	}
	
}

Open in new window


Here is the code for the ThreadExample Class:

What this does is create a thread.  Then when the 'Start' method is invoked... from the Main code above... the run method will be executed in the ThreadExample class.

So what I have the ThreadExample do when it runs... is to add one to its Counter Object, and then print out the not only which thread did it... but also what the new value is.

package ee.com;

public class ThreadExample extends Thread{

	private Counter aCounterInstance;
	private String threadID;
	
	public ThreadExample(Counter someCounter,String threadIdentifier) {
		this.aCounterInstance = someCounter;
		this.threadID = threadIdentifier;
	}
	
	public void run(){
		
		for(int i=0;i<5;i++) {
			aCounterInstance.addToCount();
			System.out.println("Thread " + this.threadID + " just incremented Count to " + this.aCounterInstance.getCount());
		}
	}
}

Open in new window


Here is the output I got when a ran the application:
Thread firstThread just incremented Count to 1
Thread firstThread just incremented Count to 3
Thread firstThread just incremented Count to 4
Thread firstThread just incremented Count to 5
Thread firstThread just incremented Count to 6
Thread secondThread just incremented Count to 2
Thread secondThread just incremented Count to 7
Thread secondThread just incremented Count to 8
Thread secondThread just incremented Count to 9
Thread secondThread just incremented Count to 10

Open in new window

0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 
LVL 7

Author Comment

by:gudii9
ID: 39871318
i got output in haphazard way compared to your output in orderly way

Thread firstThread just incremented Count to 1
Thread firstThread just incremented Count to 3
Thread secondThread just incremented Count to 2
Thread firstThread just incremented Count to 4
Thread firstThread just incremented Count to 6
Thread secondThread just incremented Count to 5
Thread firstThread just incremented Count to 7
Thread secondThread just incremented Count to 8
Thread secondThread just incremented Count to 9
Thread secondThread just incremented Count to 10


please advise how to get in orderly way?
0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39871471
the system.out.println has a buffer... so the two threads will not necessarily always print out at the same time.

You should expect that if you keep rerunning it over and over the output will vary.
This would be expected.

If you want to see the output more orderly... more consistent... then I'd advise moving the system.out.println to the addToCount function.

Probably would also help to clear the buffer with System.Out.Flush().

So the modified code would look like this...


package ee.com;

public class Counter {

	private int count;
	
	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public synchronized void addToCount() {
		this.count++;
                System.out.println("Thread " + this.threadID + " just incremented Count to " + this.aCounterInstance.getCount());
                System.out.flush();
	}
	
}

Open in new window


(also would need to remove the other System.out.println... so that you don't have it in two places at once).

You should keep in mind that the random output is a good demonstration of threads.
Threads should be used in your code when order is not important... but instead, when you have several tasks that all need to be completed, and they can also be completed independently of one another.

When working with threads it is not important to get orderly output.  If it is important... then it is a most likely a poor implementation of threading.

As an after thought on that code... you would also have to pass in the thread ID to the Counter so that it could be printed on the system.out.println.


I'm not really interested in reworking the classes to do that... because it is not relevant to the original question anyway.
0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39871537
Thought about it some more...

the two changes would help to demonstrate differences of using the wait/notify vs. not...
so I'll add them here in two different posts.

I think the reason it makes such a big difference here is that relatively speaking the System.out.println and the System.out.flush are somewhat time consuming... so you can really see the threads waiting (or not waiting) as the case may be.

Here is with the wait notify added in the Counter Class.

First the main class:

package ee.com;

public class MyExample {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Counter myCounter = new Counter();
		
		ThreadExample firstThread = new ThreadExample(myCounter,"firstThread");
		ThreadExample secondThread = new ThreadExample(myCounter,"secondThread");
		
		firstThread.start();
		secondThread.start();
		
	}

}

Open in new window


Second the ThreadExample Class:
package ee.com;

public class ThreadExample extends Thread{

	private Counter aCounterInstance;
	private String threadID;
	
	public ThreadExample(Counter someCounter,String threadIdentifier) {
		this.aCounterInstance = someCounter;
		this.threadID = threadIdentifier;
	}
	
	public void run(){
		
		for(int i=0;i<5;i++) {
			aCounterInstance.addToCount(threadID);
		}
	}
}

Open in new window


Third the Counter Class:

package ee.com;

public class Counter {

	private int count;
	
	Counter() {
		this.count = 0;
	}
	
	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public synchronized void addToCount(String threadName) {
			this.notify();
		this.count++;
		System.out.println("Thread " + threadName + " just incremented Count to " + count);
		System.out.flush();
		try {
			this.wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}

Open in new window


The Output :
Thread firstThread just incremented Count to 1
Thread secondThread just incremented Count to 2
Thread firstThread just incremented Count to 3
Thread secondThread just incremented Count to 4
Thread firstThread just incremented Count to 5
Thread secondThread just incremented Count to 6
Thread firstThread just incremented Count to 7
Thread secondThread just incremented Count to 8
Thread firstThread just incremented Count to 9
Thread secondThread just incremented Count to 10

Open in new window

0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39871550
Now the only change I'll make from previous post is from the Counter class to remove the wait/notify.

Counter Class:

package ee.com;

public class Counter {

	private int count;
	
	Counter() {
		this.count = 0;
	}
	
	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public synchronized void addToCount(String threadName) {
		this.count++;
		System.out.println("Thread " + threadName + " just incremented Count to " + count);
		System.out.flush();
		
	}
	
}

Open in new window


Note that this can vary if you run it multiple times... but because the count is synchronized... and you display the count in synchronized routine, the displayed order from 1 to 10 should always be accurate... but the order the threads execute may not be the same each time.


Thread firstThread just incremented Count to 1
Thread firstThread just incremented Count to 2
Thread secondThread just incremented Count to 3
Thread secondThread just incremented Count to 4
Thread secondThread just incremented Count to 5
Thread secondThread just incremented Count to 6
Thread secondThread just incremented Count to 7
Thread firstThread just incremented Count to 8
Thread firstThread just incremented Count to 9
Thread firstThread just incremented Count to 10

Open in new window


Reran ... (unchanged code):
Thread firstThread just incremented Count to 1
Thread firstThread just incremented Count to 2
Thread firstThread just incremented Count to 3
Thread firstThread just incremented Count to 4
Thread firstThread just incremented Count to 5
Thread secondThread just incremented Count to 6
Thread secondThread just incremented Count to 7
Thread secondThread just incremented Count to 8
Thread secondThread just incremented Count to 9
Thread secondThread just incremented Count to 10

Open in new window


Now in this last example... I removed synchronized altogether... and since both threads access the same object... the output is completely unknown.  (actually the output was slightly more orderly than I expected it to be).


Thread firstThread just incremented Count to 1
Thread secondThread just incremented Count to 2
Thread secondThread just incremented Count to 4
Thread secondThread just incremented Count to 5
Thread secondThread just incremented Count to 6
Thread firstThread just incremented Count to 3
Thread secondThread just incremented Count to 7
Thread firstThread just incremented Count to 8
Thread firstThread just incremented Count to 9
Thread firstThread just incremented Count to 10

Open in new window

0
 
LVL 7

Author Comment

by:gudii9
ID: 39880957
Excellent makes more sense. Using synchronized seems more clean approach
public synchronized void addToCount(String threadName) {

compare to

public synchronized void addToCount(String threadName) {
                  this.notify();
            this.count++;
            System.out.println("Thread " + threadName + " just incremented Count to " + count);
            System.out.flush();
            try {
                  this.wait();
            } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
            

Which one supposed to be used when
Also why notify came first line of above method (addToCount())

where as wait is coming almost last line. is it not supposed to be other way where wait should come and once all done notify has to be triggered ? please advise
0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39881576
Try switching the wait/Notfify positions and see what happens.

I expect that your eclipse session will lock up.  You will probably have to kill the job.

The Wait puts the thread that is processing to sleep.  If you put the wait first in this case... then the wait is what both threads will hit first.  In a sense... you will have knocked both threads unconscious... and now there is nobody left to wake anyone up!

The wait / notify combination should be used to put a thread to sleep that might otherwise be doing nothing anyway.  Putting it to sleep would be preferable to having it using up CPU cycle's unnecessarily.

I'll try to make up a situation...

Let's say I have one thread whose job is going to be to determine the average score on a test.

Let's say I have 10,000 tests that have to be graded.   Maybe I'll create 10 threads whose job is to grade the tests.

I might put execute a "Wait" on the thread whose job is to take the average... because the average cannot be computed until all the tests are graded.

Once all the tests are graded...then the "grading" threads can issue a Notify... which means that Notify the "Averaging" thread that it can go forward... because now all the tests are graded.

The Notify will "wake-up" the waiting thread... and now it can complete it's assigned task.

As you can see from the prior example of the counter... a wait and notify do not necessarily have to be used when you use a synchronize.... it totally depends upon what you are trying to accomplish.
0
 
LVL 7

Author Comment

by:gudii9
ID: 39890379
he Wait puts the thread that is processing to sleep.

you mean main thread or thread1
0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39890498
If a thread executes the Wait instruction, that thread will be put to sleep.

There is no difference if it is main thread or thread1, or any other thread.
0
 
LVL 7

Author Comment

by:gudii9
ID: 39930536
I am still digesting this post.

the system.out.println has a buffer... so the two threads will not necessarily always print out at the same time.


How much time it has buffer?

please advise
0
 
LVL 19

Accepted Solution

by:
Ken Butters earned 500 total points
ID: 39932167
buffering is how a class is implemented.  So classes that have a buffer, always have buffer.

As a developer, you do not have any control over the size of the buffer or how it is implemented.
--- or have to worry about it unless you specifically want to flush the buffer, which is only if you absolutely require that the buffer be emptied at a specific time.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question