Two threads a producer one consumer
Demand Scenarios
- Two threads, one responsible for production, one responsible for consumption, the producer produces one, the consumer consumes a
Issues involved
- Synchronization issues: How to ensure the integrity of the same resource when it is concurrently accessed by multiple threads. The common method of synchronization is to use the tag or lock mechanism
- The wait ()/nofity () method is the two method of the base class object, which means that all Java classes will have both methods, so that we can implement synchronization mechanisms for any object.
- Wait () method: When the buffer is full/empty, the producer/consumer thread stops its own execution, discards the lock, keeps itself in the state, and lets other threads execute it.
- Notify () method: When a producer/consumer puts a product into a buffer, it sends an executable notification to the other waiting thread while discarding the lock, leaving itself in a wait state.
Code implementation (a total of three classes and a test class for the Main method)
Resource.java
/*** Created by Yuandl on 2016-10-11./** * Resources*/ Public classResource {/*Resource Number*/ Private intNumber = 0; /*Resource Tag*/ Private BooleanFlag =false; /*** Production Resources*/ Public synchronized voidCreate () {if(flag) {//First judge whether the mark has been produced, if it has been produced, waiting for consumption; Try{wait ();//Let the production line wait}Catch(interruptedexception e) {e.printstacktrace (); }} number++;//produce aSystem.out.println (Thread.CurrentThread (). GetName () + "producer------------" +Number ); Flag=true;//to mark a resource as already producedNotify ();//Wake up the thread (queue) waiting for the operation Resource } /*** Consumer Resources*/ Public synchronized voiddestroy () {if(!flag) { Try{wait (); } Catch(interruptedexception e) {e.printstacktrace (); }} System.out.println (Thread.CurrentThread (). GetName ()+ "Consumer * * * *" +Number ); Flag=false; Notify (); }}
Producer.java
/*** Created by Yuandl on 2016-10-11. */** * producerhttp://www.manongjc.com */ Public classProducerImplementsRunnable {PrivateResource Resource; PublicProducer (Resource Resource) { This. Resource =resource; } @Override Public voidrun () { while(true) { Try{Thread.Sleep (10); } Catch(interruptedexception e) {e.printstacktrace (); } resource.create (); } }}
Consumer.java
/*** Consumer*/ Public classConsumerImplementsRunnable {PrivateResource Resource; PublicConsumer (Resource Resource) { This. Resource =resource; } @Override Public voidrun () { while(true) { Try{Thread.Sleep (10); } Catch(interruptedexception e) {e.printstacktrace (); } Resource.destroy (); } }}
Producerconsumertest.java
/*** Created by Yuandl on 2016-10-11.*/ Public classProducerconsumertest { Public Static voidMain (String args[]) {Resource Resource=NewResource (); NewThread (NewProducer (Resource)). Start ();//Producer Threads NewThread (NewConsumer (Resource)). Start ();//Consumer Threads }}
Printing results:
Thread-0 producer------------1Thread-1 Consumer ****1Thread-0 producer------------2Thread-1 Consumer ****2Thread-0 producer------------3Thread-1 Consumer ****3Thread-0 producer------------4Thread-1 Consumer ****4Thread-0 producer------------5Thread-1 Consumer ****5Thread-0 producer------------6Thread-1 Consumer ****6Thread-0 producer------------7Thread-1 Consumer ****7Thread-0 producer------------8Thread-1 Consumer ****8Thread-0 producer------------9Thread-1 Consumer ****9Thread-0 producer------------10Thread-1 Consumer ****10
The above print results can be seen without any problems
Issues for multiple threads, multiple producers and multiple consumers
Demand Scenarios
- Four threads, two are responsible for production, two are responsible for consumption, producer production of one, consumer consumption of a
Issues involved
- Notifyall () Method: When a producer/consumer puts a product into a buffer, it sends an executable notification to all other waiting threads while discarding the lock, leaving itself in a wait state.
Test the code again
Producerconsumertest.java
* * Created by Yuandl on 2016-10-11. */ Public classProducerconsumertest { Public Static voidMain (String args[]) {Resource Resource=NewResource (); NewThread (NewConsumer (Resource)). Start ();//Producer Threads NewThread (NewConsumer (Resource)). Start ();//Producer Threads NewThread (NewProducer (Resource)). Start ();//Consumer Threads NewThread (NewProducer (Resource)). Start ();//Consumer Threads }}
Operation Result:
Thread-0 producer------------100Thread-3 Consumer ****100Thread-0 producer------------101Thread-3 Consumer ****101Thread-2 consumer ****101Thread-1 producer------------102Thread-3 Consumer ****102Thread-0 producer------------103Thread-2 consumer ****103Thread-1 producer------------104Thread-3 Consumer ****104Thread-1 producer------------105Thread-0 producer------------106Thread-2 consumer ****106Thread-1 producer------------107Thread-3 Consumer ****107Thread-0 producer------------108Thread-2 consumer ****108Thread-0 producer------------109Thread-2 consumer ****109Thread-1 producer------------110Thread-3 Consumer ****110
Find problems with the above print results
- 101 was produced once and consumed twice
- 105 production, and no consumption
Cause analysis
- When two threads operate concurrently with producer production or consumer consumption, if there is a producer or two threads Wait (), again notify (), because one of the threads has changed the tag while another thread is executing directly again without judging the token.
- If the flag is judged only once, it causes the thread that should not run to run. A case of data error occurred.
Solution Solutions
- While judging the flag, resolves if the thread gets execution right after it is run! That is, after each wait () and then notify () the first time to judge the mark
Code improvements (If->while in Resource)
Resource.java
/*** Created by Yuandl on 2016-10-11./** * Resources*/ Public classResource {/*Resource Number*/ Private intNumber = 0; /*Resource Tag*/ Private BooleanFlag =false; /*** Production Resources*/ Public synchronized voidCreate () { while(flag) {//First judge whether the mark has been produced, if it has been produced, waiting for consumption; Try{wait ();//Let the production line wait}Catch(interruptedexception e) {e.printstacktrace (); }} number++;//produce aSystem.out.println (Thread.CurrentThread (). GetName () + "producer------------" +Number ); Flag=true;//to mark a resource as already producedNotify ();//Wake up the thread (queue) waiting for the operation Resource } /*** Consumer Resources*/ Public synchronized voiddestroy () { while(!flag) { Try{wait (); } Catch(interruptedexception e) {e.printstacktrace (); }} System.out.println (Thread.CurrentThread (). GetName ()+ "Consumer * * * *" +Number ); Flag=false; Notify (); }}
Discover the problem again
- Print to a value such as the production of 74, the program runs the card dead, as if the lock dead.
Cause analysis
- Notify: Only one thread can be awakened, if this party wakes up the party, it is meaningless. And while judging the token +notify will cause "deadlock".
Solution Solutions
- notifyall resolves an issue in which the thread of this party will surely wake the other thread.
Final Code improvements (notify ()->notifyall () in Resource)
Resource.java
/*** Created by Yuandl on 2016-10-11./** * Resources*/ Public classResource {/*Resource Number*/ Private intNumber = 0; /*Resource Tag*/ Private BooleanFlag =false; /*** Production Resources*/ Public synchronized voidCreate () { while(flag) {//First judge whether the mark has been produced, if it has been produced, waiting for consumption; Try{wait ();//Let the production line wait}Catch(interruptedexception e) {e.printstacktrace (); }} number++;//produce aSystem.out.println (Thread.CurrentThread (). GetName () + "producer------------" +Number ); Flag=true;//to mark a resource as already producedNotifyall ();//Wake up the thread (queue) waiting for the operation Resource } /*** Consumer Resources*/ Public synchronized voiddestroy () { while(!flag) { Try{wait (); } Catch(interruptedexception e) {e.printstacktrace (); }} System.out.println (Thread.CurrentThread (). GetName ()+ "Consumer * * * *" +Number ); Flag=false; Notifyall (); }}
Operation Result:
Thread-0生产者------------412Thread-2消费者****412Thread-0生产者------------413Thread-3消费者****413Thread-1生产者------------414Thread-2消费者****414Thread-1生产者------------415Thread-2消费者****415Thread-0生产者------------416Thread-3消费者****416Thread-1生产者------------417Thread-3消费者****417Thread-0生产者------------418Thread-2消费者****418Thread-0生产者------------419Thread-3消费者****419Thread-1生产者------------420Thread-2消费者****420
That's it, no problem.
Original address: http://www.manongjc.com/article/1583.html
Java multi-thread concurrent collaboration producer consumer design patterns