Java multi-thread concurrent collaboration producer consumer design mode and producer Design Mode

Source: Internet
Author: User

Java multi-thread concurrent collaboration producer consumer design mode and producer Design Mode
Two threads, one producer, and 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 for 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 http://www.manongjc.com */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 result:

Thread-0 producer ---------- 1Thread-1 consumer ***** 1Thread-0 producer ---------- 2Thread-1 consumer ***** 2Thread-0 producer ---------- 3Thread-1 consumer ***** producer ---------- 4Thread-1 consumer ***** 4Thread-0 producer ------------ 5Thread-1 consumer ***** 5Thread-0 producer ------------ 6Thread-1 consumer ***** producer ------------ 7Thread-1 consumer ***** producer ---------- 8Thread-1 consumer ***** producer ---------- 9Thread-1 consumer * * ** 9Thread-0 producer ---------- 10Thread-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 ------------ 100Thread-3 consumer ***** 100Thread-0 producer ---------- 101Thread-3 consumer ****** 101Thread-2 consumer ****** 101Thread-1 producer ---------- 103Thread-2 consumer ***** producer ---------- 103Thread-2 consumer * *** 103Thread-1 producer ---------- bytes thread-3 consumer ***** bytes thread-1 producer ------------ bytes thread-2 consumer ***** bytes thread-1 producer ------------ bytes thread-3 consumer ***** bytes producer ---------- bytes thread-2 consumer * * ** producer thread-0 producer ---------- consumer thread-2 *** producer thread-1 producer ---------- 110Thread-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 ---------- 412Thread-2 consumer ***** producer ---------- 413Thread-3 consumer ***** 413Thread-1 producer ---------- 414Thread-2 consumer ***** producer ---------- consumer thread-2 consumer ***** thread-0 producer ------------ 416Thread-3 consumer ***** 416Thread-1 producer ------------ worker thread-3 consumer ***** producer ------------ 418Thread-2 consumer ***** producer ---------- 419Thread-3 consumer ***** 419Thread-1 producer ------------ consumer * * ** 420

The above is all done, and there is no problem

Address: http://www.manongjc.com/article/1583.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.