Interaction between threads
Interaction between threads: there is a need for some coordinated communication between threads to accomplish a task together.
The related methods in the object class have two notify methods and three wait methods:
Http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
Because the wait and notify methods are defined in the object class, they are inherited by all classes.
These methods are final , that is, they cannot be rewritten and cannot be overridden by subclasses to alter their behavior.
Wait () method
The wait () method causes the current thread to wait until another thread calls the Notify () or Notifyall () method.
The current thread must have the monitor for the current object, or lock, which is the lock.
The thread calls the Wait () method, frees its ownership of the lock, and waits for another thread to notify it (the notification is in the Notify () or Notifyall () method) so it can regain ownership of the lock and resume execution.
To ensure that you have a lock when you call the Wait () method, the call to the wait () method must be placed in the synchronized method or synchronized block.
A small comparison:
When a thread calls the Wait () method, it releases the lock on the object.
Another method that causes the thread to pause: Thread.Sleep (), which causes the thread to sleep for a specified number of milliseconds, but the thread does not release the lock on the object during sleep.
Notify () method
The Notify () method wakes up a thread that waits for a lock on the current object.
If multiple threads are waiting, one of them will choose to be awakened. This choice is arbitrary and relevant to the specific implementation. (a thread waits for a lock on an object because it calls one of the wait methods.)
A thread that is awakened cannot be executed and needs to wait until the current thread discards the lock on the object.
The awakened thread will compete with other threads in the usual way to get the lock on the object. In other words, the awakened thread does not have any priority or disadvantage, and the next thread of the object needs to compete in general.
The Notify () method should be called by the thread that owns the lock for the object.
(This method should only being called by a thread that's the owner of this object ' s monitor.)
In other words, like the Wait () method, the Notify method call must be placed in the synchronized method or synchronized block.
The Wait () and notify () methods require that the thread has acquired the lock on the object at the time of invocation, so calls to both methods need to be placed in the synchronized method or synchronized block.
The owner of a lock that becomes a thread of an object is done in the following three ways:
1. Execute the Synchronized instance method for this object.
2. Execute the SYNCHRONIZED statement block for this object. This object is locked by this block of statements.
3. For the Class class object, execute the synchronized, static method of that category.
Program examples
With two threads, a change is made to an shaping member variable, one to increase it, one to reduce it, and to make use of the communication between the threads to realize the alternating change of the shaping variable 0101.
Numbertest
public class Numberholder
{
private int number;
Public synchronized void Increase ()
{
if (0! = number)
{
Try
{
Wait ();
}
catch (Interruptedexception e)
{
E.printstacktrace ();
}
}
Be able to perform to here the explanation has been awakened
and number is 0.
number++;
SYSTEM.OUT.PRINTLN (number);
Notifies the waiting thread
Notify ();
}
Public synchronized void decrease ()
{
if (0 = = number)
{
Try
{
Wait ();
}
catch (Interruptedexception e)
{
E.printstacktrace ();
}
}
Be able to perform to here the explanation has been awakened
And number is not 0.
number--;
SYSTEM.OUT.PRINTLN (number);
Notify ();
}
}
public class Increasethread extends Thread
{
Private Numberholder Numberholder;
Public Increasethread (Numberholder numberholder)
{
This.numberholder = Numberholder;
}
@Override
public void Run ()
{
for (int i = 0; i <; ++i)
{
For a certain delay.
Try
{
Thread.Sleep ((Long) math.random () * 1000);
}
catch (Interruptedexception e)
{
E.printstacktrace ();
}
To increase the operation
Numberholder.increase ();
}
}
}
public class Decreasethread extends Thread
{
Private Numberholder Numberholder;
Public Decreasethread (Numberholder numberholder)
{
This.numberholder = Numberholder;
}
@Override
public void Run ()
{
for (int i = 0; i <; ++i)
{
For a certain delay.
Try
{
Thread.Sleep ((Long) math.random () * 1000);
}
catch (Interruptedexception e)
{
E.printstacktrace ();
}
To reduce operations
Numberholder.decrease ();
}
}
}
public class Numbertest
{
public static void Main (string[] args)
{
Numberholder Numberholder = new Numberholder ();
Thread T1 = new Increasethread (Numberholder);
Thread t2 = new Decreasethread (Numberholder);
T1.start ();
T2.start ();
}
}
public class numberholder{private int number; Public synchronized void Increase () {if (0! = number) {try {wait ( ); } catch (Interruptedexception e) {e.printstacktrace (); }}//Can execute to here the description has been awakened//and number is 0 number++; SYSTEM.OUT.PRINTLN (number); Notifies the waiting thread of Notify (); Public synchronized void decrease () {if (0 = = number) {try { Wait (); } catch (Interruptedexception e) {e.printstacktrace (); }}//Can be performed here to indicate that it has been awakened//and number is not 0 number--; SYSTEM.OUT.PRINTLN (number); Notify (); }}public class Increasethread extends thread{private Numberholder numberholder; Public Increasethread (Numberholder numberholder) {this.numberholder = Numberholder; } @Override public void Run () {for (int i = 0; i <; ++i) {//Perform a certain delay T ry {thread.sleep (long) math.random () * 1000); } catch (Interruptedexception e) {e.printstacktrace (); }//To increase Operation Numberholder.increase (); }}}public class Decreasethread extends thread{private Numberholder numberholder; Public Decreasethread (Numberholder numberholder) {this.numberholder = Numberholder; } @Override public void Run () {for (int i = 0; i <; ++i) {//Take a certain delay try {thread.sleep (long) math.random () * 1000); } catch (Interruptedexception e) {e.printstacktrace (); }//To reduce Operation Numberholder.decrease (); }}}public class numbertest{public static void MAin (string[] args) {Numberholder numberholder = new Numberholder (); Thread T1 = new Increasethread (Numberholder); Thread t2 = new Decreasethread (Numberholder); T1.start (); T2.start (); }}
What if we add two more threads?
Change the Numbertest class to read as follows:
Numbertest 4 Threads
public class Numbertest
{
public static void Main (string[] args)
{
Numberholder Numberholder = new Numberholder ();
Thread T1 = new Increasethread (Numberholder);
Thread t2 = new Decreasethread (Numberholder);
Thread t3 = new Increasethread (Numberholder);
Thread T4 = new Decreasethread (Numberholder);
T1.start ();
T2.start ();
T3.start ();
T4.start ();
}
}
public class numbertest{public static void Main (string[] args) { Numberholder numberholder = new Numberholder (); Thread T1 = new Increasethread (numberholder); Thread t2 = new Decreasethread (numberholder); Thread t3 = new Increasethread (numberholder); Thread T4 = new Decreasethread (numberholder); T1.start (); T2.start (); T3.start (); T4.start (); }}
After the operation found, plus T3 and T4 after the result is wrong.
Why is it wrong to execute two threads with the correct results and four threads?
Because the thread is in wait (), it receives notifications from other threads, which are executed down and no longer judged. Two threads, the wake is definitely another thread, but in the case of multiple threads, execution results are chaotic.
For example, one possible scenario is that when an additional thread executes, the other three threads are waiting, when the first thread calls the Notify () method, the other threads are awakened, and then the respective increment or decrease method is executed.
the solution is to still make conditional judgments after being awakened , to check if the number to be changed satisfies the condition, and to continue to sleep if the condition is not met. change the If of the two methods to a while.
Numberholder 4 Threads
public class Numberholder
{
private int number;
Public synchronized void Increase ()
{
while (0! = number)
{
Try
{
Wait ();
}
catch (Interruptedexception e)
{
E.printstacktrace ();
}
}
Be able to perform to here the explanation has been awakened
and number is 0.
number++;
SYSTEM.OUT.PRINTLN (number);
Notifies the waiting thread
Notify ();
}
Public synchronized void decrease ()
{
while (0 = = number)
{
Try
{
Wait ();
}
catch (Interruptedexception e)
{
E.printstacktrace ();
}
}
Be able to perform to here the explanation has been awakened
And number is not 0.
number--;
SYSTEM.OUT.PRINTLN (number);
Notify ();
}
}
public class numberholder{ private int number; Public synchronized void Increase () { while (0! = number) { Try { wait (); } catch (interruptedexception e) { e.printstacktrace (); } } Can perform to here the description has been awakened //and number is 0 number++; SYSTEM.OUT.PRINTLN (number); Notifies the waiting thread of notify (); } Public synchronized void decrease () { while (0 = = number) { Try { wait (); } catch (interruptedexception e) { e.printstacktrace (); } } Can perform to here the description has been awakened //and number is not 0 number--; SYSTEM.OUT.PRINTLN (number); Notify (); }}
Resources
Santhiya Garden Zhang Long teacher Java SE Series video tutorial.
Java Multithreading (vii) Communication--wait and notify methods between threads