Multiple threads are working on the same resource, but the tasks of the threads are not the same, so that each thread can use the resources efficiently by some means.
This means: Waiting for a wake-up mechanism, also known as communication between threads
Methods involved: Wait (), notify ()
Example:
Two threads one input, one output
Package demo; Public class Resource { public String name; Public String sex;}
Input thread:
Packagedemo; Public classInputImplementsRunnable {PrivateResource r =NewResource (); Public voidrun () {inti = 0; while(true) { if(i% 2 = = 0) {R.name= "Zhang San"; R.sex= "Male"; } Else{r.name= "John Doe"; R.sex= "female"; } I++; } }}
Output thread:
Package demo; Public class Implements Runnable { privatenew Resource (); Public void run () { while (true) { System.out.println (r.name+ "..." + r.sex); }}}
Test class:
Package demo; Public class Threaddemo { publicstaticvoid main (string[] args) { new Input (); New Output (); New Thread (in); New Thread (out); Tin.start (); Tout.start (); }}
After running, we find that the output is Null...null
Because the input thread and the resource object created in the output thread make different
Resolve NULL Issues:
Packagedemo; Public classInputImplementsRunnable {PrivateResource R; PublicInput (Resource r) { This. R =R; } Public voidrun () {inti = 0; while(true) { if(i% 2 = = 0) {R.name= "Zhang San"; R.sex= "Male"; } Else{r.name= "John Doe"; R.sex= "female"; } I++; } }}
package demo; public class Output implements Runnable { private Resource R; public Output (Resource r) { this . R = R; public void run () { while (true + "..." +r.sex); } }}
Packagedemo; Public classThreaddemo { Public Static voidMain (string[] args) {Resource R=NewResource (); Input in=NewInput (R); Output out=NewOutput (R); Thread Tin=NewThread (in); Thread Tout=NewThread (out); Tin.start (); Tout.start (); }}
Another problem was discovered after running:
The output contains: Zhang San ... Female or Li four ... Male, sex error
Cause of Occurrence:
After the assignment of Zhang San and male, continue to assign value John Doe and female, this time has not yet and the assignment of female, entered the output thread, then output John Doe ... Man
So I thought of adding synchronization:
Public voidrun () {inti = 0; while(true) { synchronized( This) { if(i% 2 = = 0) {R.name= "Zhang San"; R.sex= "Male"; } Else{r.name= "John Doe"; R.sex= "female"; } I++; } } }
Public void run () { while (true) { synchronized (this ) { + "..." + r.sex); }}}
However, the problem has not been solved:
Reason:
The synchronization here has lost its function, not a lock.
Workaround:
Use a common lock to
Public voidrun () {inti = 0; while(true) { synchronized(r) {if(i% 2 = = 0) {R.name= "Zhang San"; R.sex= "Male"; } Else{r.name= "John Doe"; R.sex= "female"; } I++; } } }
Public void run () { while (true) { synchronized (r) { + "..." + r.sex); }}}
This is the normal output.
But there is still a problem, we hope that the Zhang San and John Doe staggered, a 31 John Doe, is still random, large tracts of Zhang San or John Doe
Workaround:
Let the input thread assign a value, then let the output thread out, and let the incoming thread wait, not allow the assignment of John Doe, wait for output Zhang San end, then allow Li Shiyi value, go down
The input thread also needs the same way, and waits after the output is finished
The wait-and-wake mechanism is needed:
Input: After assignment, execution method Wait () Waits forever
Output: After printing, before output waits, wake-up input notify (), and then wait () forever
Input: After being awakened, re-assigned, must notify () wake up the output of the thread, and then wait ()
Loop down in turn
Code implementation:
Package demo; Public class Resource { public String name; Public String sex; Public Boolean false ;}
Packagedemo; Public classInputImplementsRunnable {PrivateResource R; PublicInput (Resource r) { This. R =R; } Public voidrun () {inti = 0; while(true) { synchronized(r) {if(r.flag) {Try{r.wait (); } Catch(Exception e) {}}if(i% 2 = = 0) {R.name= "Zhang San"; R.sex= "Male"; } Else{r.name= "John Doe"; R.sex= "female"; } R.flag=true; R.notify (); } I++; } }}
Packagedemo; Public classOutputImplementsRunnable {PrivateResource R; PublicOutput (Resource r) { This. R =R; } Public voidrun () { while(true) { synchronized(r) {if(!r.flag) {Try{r.wait (); } Catch(Exception e) {}} System.out.println (R.name+ "..." +r.sex); R.flag=false; R.notify (); } } }}
Packagedemo; Public classThreaddemo { Public Static voidMain (string[] args) {Resource R=NewResource (); Input in=NewInput (R); Output out=NewOutput (R); Thread Tin=NewThread (in); Thread Tout=NewThread (out); Tin.start (); Tout.start (); }}
This is the Dick and Harry interleaved output.
Complete
Java Learning Note 46 (multithreading three: communication between threads)