Solved

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

Posted on 2014-02-11
13
825 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
  • 7
  • 5
13 Comments
 
LVL 35

Expert Comment

by:mccarl
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 7

Author Comment

by:gudii9
Comment Utility
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
Comment Utility
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
Comment Utility
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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 19

Expert Comment

by:Ken Butters
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
he Wait puts the thread that is processing to sleep.

you mean main thread or thread1
0
 
LVL 19

Expert Comment

by:Ken Butters
Comment Utility
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
Comment Utility
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
Comment Utility
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

762 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now