The communication between Java multithreading
Outline of this article
I. Several states of a thread
Two. Inter-threading interactions
Three. Example code Analysis
I. Several states of a thread
Threads have four states, and any one thread must be in one of these four states:
(1). Generation (NEW): The thread object has been generated but has not been started and cannot be executed. If a thread object is generated through new, it is not called before the start () function.
(2). Executable (Runnable): Each multithreaded system has a scheduler that selects a thread from the thread pool and starts it.
When a thread is in an executable state, it indicates that it may be in the thread pool waiting for the scheduler to start it, or it may already be executing.
If the start () method of a thread object is executed, the thread is in an executable state, but it is clear that the thread is not necessarily executing at this point.
(3). Death (Dead): When a thread ends normally, it is in a dead state. A thread enters a dead state when the run () function of a thread finishes executing.
(4). Stagnation (Blocked): When a thread is stuck, the system scheduler ignores it and does not schedule it.
Two. Inter-threading interactions
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.
Wait () compared to sleep ()
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 has no priority and no disadvantage,
The next thread of the object still needs to pass general competition.
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.
Three. Example code Analysis
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.
/** * To reduce the operation of the thread. * @author Cary * @version 1.0.0*/ Public classDecreasethread extends thread{PrivateNumberholder Numberholder; PublicDecreasethread (Numberholder numberholder) { This. Numberholder =Numberholder; } @Override Public voidrun () { for(inti =0; I < -; ++i) {/** * For a certain delay*/ Try{Thread.Sleep (Long) Math.random () * +); } Catch(interruptedexception e) {e.printstacktrace (); } /** * for reduced operation*/numberholder.decrease (); } }}
/**
* Thread to increase the operation.
*
* @author Cary
* @version 1.0.0
*/
public class Increasethread extends Thread {
Private Numberholder Numberholder;
Public Increasethread (Numberholder numberholder) {
This.numberholder = Numberholder;
}
@Override
/**
* for a certain delay
*/
try {
Thread.Sleep ((long) math.random () * +);
"catch (Interruptedexception e) {
E.printstacktrace ();
/**
* For increased operation
*/
Numberholder.increase ();
}
}
}
/**
* Thread to reduce the operation.
*
* @author Cary
* @version 1.0.0
*/
public class Decreasethread extends Thread {
Private Numberholder Numberholder;
Public Decreasethread (Numberholder numberholder) {
This.numberholder = Numberholder;
}
@Override
/**
* for a certain delay
*/
try {
Thread.Sleep ((long) math.random () * +);
"catch (Interruptedexception e) {
E.printstacktrace ();
/**
* For reduced operation
*/
Numberholder.decrease ();
}
}
}
/**
* Thread testing.
* @author Cary
* @version 1.0.0
*/
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 ();
}
}
If you add 2 more threads, change the Numbertest class to read as follows:
Public classnumbertest{ Public Static voidMain (string[] args) {Numberholder Numberholder=NewNumberholder (); Thread T1=NewIncreasethread (Numberholder); Thread T2=NewDecreasethread (Numberholder); Thread T3=NewIncreasethread (Numberholder); Thread T4=NewDecreasethread (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. In the case of two threads, the wake is definitely another thread;
However, 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,
Other threads will be awakened, and then the respective increment or decrease methods are 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.
Public classnumberholder{Private intNumber ; PublicSynchronizedvoidIncrease () { while(0!=Number ) { Try{wait (); } Catch(interruptedexception e) {e.printstacktrace (); } } //can execute to here the description has been awakened, and number is not 0number++; System. out. println (number); //notifies the waiting threadnotify (); } PublicSynchronizedvoiddecrease () { while(0==Number ) { Try{wait (); } Catch(interruptedexception e) {e.printstacktrace (); } } //can execute to here the description has been awakened, and number is not 0number--; System. out. println (number); Notify (); }}
Java Multithreading (6)-Inter-thread communication wait and notify method