The purpose of thread communication is to enable threads to send signals to each other. In addition, thread communication enables threads to wait for signals from other threads, for example, thread B can wait for the signal of thread A, which can be a signal that thread A has already processed. communicating through shared objects
A simple way to implement communication between threads is to set a signal value in a variable of a shared object. For example, thread a sets a member variable hasdatatoprocess value to True in a synchronization block, while thread B reads the member variable in a synchronized block as well. The following example shows an object holding a signal value and provides a synchronization method that sets the signal value and gets the signal value:
public class Mysignal {
private boolean hasdatatoprocess;
Public synchronized void Sethasdatatoprocess (Boolean hasData) {
this.hasdatatoprocess=hasdata;
}
Public synchronized Boolean hasdatatoprocess () {return
this.hasdatatoprocess;
}
}
THREADB the completion of the calculation will set the signal value in the shared object:
public class THREADB extends thread{
int count;
Mysignal mysignal;
Public threadb (mysignal mysignal) {
this.mysignal=mysignal;
}
@Override public
Void Run () {for
(int i=0;i<100;i++) {
count=count+1
}
try {
thread.sleep;
} catch (Interruptedexception e) {
e.printstacktrace ();
}
Mysignal.sethasdatatoprocess (True);
}
Threada always detects the signal value of the shared object in the loop, waiting for the THREADB to compute the completed signal:
public class Threada extends thread{
mysignal mysignal;
THREADB threadb;
Public Threada (mysignal mysignal, threadb threadb) {
this.mysignal=mysignal;
this.threadb=threadb;
}
@Override public
Void Run () {while
(true) {
if (mysignal.hasdatatoprocess ()) {
System.out.println () Thread B Calculates the result as: "+threadb.count";
break;
}
}} public static void Main (string[] args) {
mysignal mysignal=new mysignal ();
THREADB threadb=new threadb (mysignal);
Threada threada=new Threada (mysignal,threadb);
Threadb.start ();
Threada.start ();
}
It is clear that thread A and thread B, which communicates with shared objects, must hold a reference to the same Mysignal object so that they can detect each other's signal. Of course, the signal can also be stored in the shared memory buffer, which is separate from the instance. threads are busy and so on
As you can see from the example above, thread A has been waiting for data to be ready, or thread A has been waiting for thread B to set the hasdatatoprocess signal value to true:
public void Run () {while
(true) {
if (mysignal.hasdatatoprocess ()) {
System.out.println ("Thread B evaluates to:" + Threadb.count);
break;
}}}
Why do you say you are busy and so on. Because the code above executes the loop until Hasdatatoprocess is set to true.
Busy, etc. means that the thread is still in the running state, has been consuming CPU resources, so, busy and so is not a very good phenomenon. Can you let the thread release CPU resources into the blocking state while waiting for the signal? In fact, Java.lang.Object provides the wait (), notify (), Notifyall () method can solve the busy and so on. Wait (), notify (), Notifyall ( )
Java provides an inline mechanism that allows a thread to enter a non running state while waiting for a signal. When a thread calls the Wait () method on any object, it enters a notify state until another thread calls the () or Notifyall () method on the same object.
In order to be able to invoke the wait (), notify () method of an object, the calling thread must first obtain the lock on the object. Because threads occupy the lock of an object only in a synchronized block, the thread must call the Wait (), notify () method in the synchronization block.
We have changed the above example of shared object communication to call object Wait (), notify () method to achieve:
First we construct an arbitrary object and we call it the monitoring object:
public class Monitorobject {
}
Threadd is responsible for the calculation and wakes the blocked THREADC when the calculation completes:
public class Threadd extends thread{
int count;
Monitorobject mysignal;
Public Threadd (Monitorobject mysignal) {
this.mysignal=mysignal;
}
@Override public
Void Run () {for
(int i=0;i<100;i++) {
count=count+1
}
try {
thread.sleep;
} catch (Interruptedexception e) {
e.printstacktrace ();
}
Synchronized (mysignal) {
mysignal.notify ()//calculation completes the calling object's Notify () method, which wakes up the thread that was suspended by calling this object Wait () method
}
}
THREADC waiting for Threadd to wake up:
public class THREADC extends thread{
monitorobject mysignal;
Threadd Threadd;
Public THREADC (Monitorobject mysignal, Threadd threadd) {
this.mysignal=mysignal;
This.threadd=threadd;
}
@Override public
Void Run () {
synchronized (mysignal) {
try {
mysignal.wait ();
} catch ( Interruptedexception e) {
e.printstacktrace ();
}
SYSTEM.OUT.PRINTLN ("Thread B evaluates to:" +threadd.count);
}
public static void Main (string[] args) {
monitorobject mysignal=new monitorobject ();
Threadd threadd=new Threadd (mysignal);
THREADC threadc=new THREADC (mysignal,threadd);
Threadc.start ();
Threadd.start ();
}
In this example, thread C hangs by invoking the Wait () method of the Monitoring object, and thread D wakes up the suspended thread C by invoking the Notify () method of the Monitoring object. We can also see that two threads are the Wait () and notify () methods that are invoked in the synchronization block. If a thread calls the wait () or notify () method of this object without obtaining an object lock, the method call throws a Illegalmonitorstateexception exception.
Note that when a thread invokes the Notify () method of an object, it wakes up a thread (the awakened thread is random) that is waiting for the thread of the object, and when it calls the object's Notifyall () method, It wakes up all the threads that are waiting for this object (which is also indeterminate in all of the awakened threads).
Here's another question, since the thread calling the object Wait () method needs to get the lock on the object, does this block the other thread from calling the object's notify () method? The answer is no blocking, and when a thread invokes the wait () method of the monitored object, it releases the monitor object lock so that other threads can call the object's notify () method or the Wait () method.
Also, when a thread wakes up, it does not immediately exit the wait () method until the thread that calls notify () exits its synchronized block. In other words, the awakened thread exits the Wait () method only when it has regain the monitor object lock, since the wait () method is in the synchronization block and its execution needs to acquire the object lock again. Therefore, when a blocked thread is awakened by the Notifyall () method, only one thread at a time can exit the wait () method, as well as each thread needs to obtain a monitoring object lock before performing the Wait () method exit in the synchronization block.