IT information, Java multi-thread concurrent collaboration producer consumer design model, UDN Developer Forum, IT technology community focusing on enterprise Internet Development two threads one producer one consumer
Requirement scenario
Two threads, one for production, one for consumption, the producer for production, and the consumer for consumption
Problems Involved
Synchronization problem: how to ensure the integrity of the same resource when it is accessed by multiple threads concurrently. A common synchronization method is to use the tag or lock mechanism.
The wait ()/nofity () method is the two methods of the base class Object, which means that all Java classes will have these two methods, so that we can implement a synchronization mechanism for any Object.
Wait () method: When the buffer zone is full or empty, the producer/consumer thread stops its execution, gives up the lock, and puts itself in the wait state for other threads to execute.
Notify () method: When the producer/consumer puts/fetches a product from the buffer, it sends an executable notification to other waiting threads and gives up the lock to keep itself in the waiting state.
Code Implementation (three classes in total and a test class for the main method)
Resource. java/***** Created by yuandl on 2016-10-11. /*** Resource */public class Resource {/* Resource no. */private int number = 0;/* Resource flag */private boolean flag = false; /*** production resource */public synchronized void create () {if (flag) {// first judge whether the mark has been produced. if it has been produced, wait for consumption; try {wait (); // wait for the production thread} catch (InterruptedException e) {e. printStackTrace () ;}} number ++; // produce a System. out. println (Thread. currentThread (). getName () + "Producer ------------" + number); flag = true; // mark the resource as running y (); // wake up the thread waiting to operate the resource (Queue )} /*** consume resource */public synchronized void destroy () {if (! Flag) {try {wait ();} catch (InterruptedException e) {e. printStackTrace () ;}} System. out. println (Thread. currentThread (). getName () + "Consumer ***" + number); flag = false; Consumer y ();}}
Producer. java
/*** Created by yuandl on 2016-10-11. */*** Producer */public class Producer implements Runnable {private Resource resource; public Producer (Resource resource) {this. resource = resource;} @ Override public void run () {while (true) {try {Thread. sleep (10);} catch (InterruptedException e) {e. printStackTrace ();} resource. create ();}}}
Consumer. java
/*** Consumer */public class Consumer implements Runnable {private Resource resource; public Consumer (Resource resource) {this. resource = resource;} @ Override public void run () {while (true) {try {Thread. sleep (10);} catch (InterruptedException e) {e. printStackTrace ();} resource. destroy ();}}}
ProducerConsumerTest. java
/*** Created by yuandl on 2016-10-11. */public class ProducerConsumerTest {public static void main (String args []) {Resource resource = new Resource (); new Thread (new Producer (resource )). start (); // producer Thread new Thread (new Consumer (resource )). start (); // consumer thread }}
Print results
Thread-0 producer ---------- 1 Thread-1 consumer ***** 1 Thread-0 producer ---------- 2 Thread-1 consumer ***** 2 Thread-0 producer ---------- 3 Thread-1 consumer * *** 3 Thread-0 producer ---------- 4 Thread-1 consumer ***** 4 Thread-0 producer ---------- 5 Thread-1 consumer ***** 5 Thread-0 producer ------------ 6 Thread-1 consumer ***** 6 Thread-0 producer ---------- 7 Thread-1 consumer ***** 7 Thread-0 producer ------------ 8 Thread-1 consumer ***** 8 thread-0 producer ---------- 9 Thread-1 consumer ***** 9 Thread-0 producer ---------- 10 Thread-1 consumer ***** 10
The above printed results show that there is no problem
Problems with multiple threads, multiple producers, and multiple consumers
Requirement scenario
Four threads, two for production, two for consumption, one for producer, and one for consumer
Problems Involved
NotifyAll () method: When the producer/consumer puts/fetches a product from the buffer, it sends an executable notification to all other threads waiting for, and gives up the lock to keep itself in the waiting state.
Test code again
ProducerConsumerTest. java/***** Created by yuandl on 2016-10-11. */public class ProducerConsumerTest {public static void main (String args []) {Resource resource = new Resource (); new Thread (new Consumer (resource )). start (); // producer Thread new Thread (new Consumer (resource )). start (); // Producer Thread new Thread (new Producer (resource )). start (); // consumer Thread new Thread (new Producer (resource )). start (); // consumer thread }}
Running result
Thread-0 producer ---------- 100 Thread-3 consumer ***** 100 Thread-0 producer ---------- 101 Thread-3 consumer ***** 101 Thread-2 consumer ***** 101 Thread -1 Producer ------------ 102 Thread-3 consumer ***** 102 Thread-0 producer ---------- 103 Thread-2 consumer ***** 103 Thread-1 Producer ---------- 104 Thread-3 consumer * * ** 104 Thread-1 Producer ------------ 105 Thread-0 producer ------------ 106 Thread-2 consumer ***** 106 Thread-1 Producer ---------- 107 Thread-3 consumer ***** 107 thread-0 producer ---------- 108 Thread-2 consumer ***** 108 Thread-0 producer ---------- 109 Thread-2 consumer ***** 109 Thread-1 Producer ---------- 110 Thread-3 consumer * *** 110
Problems found through the above printed results
101 is produced once and consumed twice
105 production, but no consumption
Cause Analysis
When two threads simultaneously operate the producer production or consumer consumption, if either the producer or both threads are wait (), notify () Again (), because one of the threads has changed the mark and the other thread does not judge the mark when it is executed directly again.
If judgment mark, only once, will cause the thread that should not run to run. Data error occurs.
Solution
The while judgment mark solves the problem of whether the thread needs to run after obtaining the execution right! That is, when wait () is followed by notify (), the flag is judged again.
Code improvement (if-> while in Resource)
Resource. java
/*** Created by yuandl on 2016-10-11. /*** Resource */public class Resource {/* Resource no. */private int number = 0;/* Resource flag */private boolean flag = false; /*** production resource */public synchronized void create () {while (flag) {// first judge whether the mark has been produced. If it has been produced, wait for consumption; try {wait (); // wait for the production thread} catch (InterruptedException e) {e. printStackTrace () ;}} number ++; // produce a System. out. println (Thread. currentThread (). getName () + "producer ------ ------ "+ Number); flag = true; // mark the resource as running y (); // wake up the thread waiting for the resource (Queue )} /*** consume resource */public synchronized void destroy () {while (! Flag) {try {wait ();} catch (InterruptedException e) {e. printStackTrace () ;}} System. out. println (Thread. currentThread (). getName () + "Consumer ***" + number); flag = false; Consumer y ();}}
Discover problems again
Print to a value, such as 74 after production, and the program is stuck, as if it was locked.
Cause Analysis
Y: Only one thread can be awakened. If this thread is awakened, it makes no sense. Besides, the while flag + running y will lead to a "deadlock ".
Solution
NotifyAll solves the problem that the local thread will wake up the other thread.
Final code improvement (notify ()-> policyall () in Resource ())
Resource. java
/*** Created by yuandl on 2016-10-11. /*** Resource */public class Resource {/* Resource no. */private int number = 0;/* Resource flag */private boolean flag = false; /*** production resource */public synchronized void create () {while (flag) {// first judge whether the mark has been produced. If it has been produced, wait for consumption; try {wait (); // wait for the production thread} catch (InterruptedException e) {e. printStackTrace () ;}} number ++; // produce a System. out. println (Thread. currentThread (). getName () + "producer ------ ------ "+ Number); flag = true; // mark the resource as producing policyall (); // wake up the thread waiting for the resource (Queue )} /*** consume resource */public synchronized void destroy () {while (! Flag) {try {wait ();} catch (InterruptedException e) {e. printStackTrace () ;}} System. out. println (Thread. currentThread (). getName () + "Consumer ***" + number); flag = false; policyall ();}}
Running result
Thread-0 producer ---------- 412 Thread-2 consumer ***** 412 Thread-0 producer ---------- 413 Thread-3 consumer ***** 413 Thread-1 Producer ---------- 414 Thread-2 consumer * *** 414 Thread-1 Producer ---------- 415 Thread-2 consumer ***** 415 Thread-0 producer ---------- 416 Thread-3 consumer ***** 416 Thread-1 Producer ------------ 417 Thread-3 consumer ***** 417 Thread-0 producer ---------- 418 Thread-2 consumer ***** 418 Thread-0 producer ------------ 419 Thread-3 consumer ***** 419 thread-1 Producer ------------ 420 Thread-2 consumer ***** 420
The above is all done, and there is no problem