Java multi-thread programming 6: communication between threads (with source code)
Source code download
In multi-threaded programming, communication between threads is a complicated problem. What are competing resources? When should I consider synchronization? How to synchronize? What is thread communication? How to communicate? Many of my friends have encountered a similar programming problem during the interview: to give a scenario, write code to properly use the waiting, notification, and notification to all threads. I believe many of my friends are familiar with the three methods of the Java. Lang. object class, such as Y, yyall, and wait, but they are not very flexible. Therefore, there are not a few friends who are hanging on the interview question during the interview. This article lists the source code of a typical producer and consumer. It illustrates this issue from the code perspective and adds the sample source code. I believe that readers will have a better understanding of the communication and interaction between threads after reading it!
The producer-consumer model is a classic in multi-threaded programs. In this source code, we will use the wait, policy, and policyall of Java. Lang. object to implement this model. This is the most important thing.
Before getting started, let's familiarize ourselves with the game rules of the producer-consumer model:
1. production is not allowed when the Warehouse is full;
2. Empty data cannot be consumed;
3. Before a consumer consumes a product, it finds that the product cannot meet the requirement. After the consumer consumes the product, it notifies the producer for production;
4. The producer notifies the consumer of consumption after producing the product.
Okay. Let's review the object lock concept before you start ...... This is the most important thing. Each object has a built-in lock. When the program runs on a non-static Synchronized Method, the lock associated with the current instance (that is, this instance) That is executing the code class is automatically obtained. This lock is not released when the java. Lang. thread. Sleep () method is executed; this lock is released when the java. Lang. Object. Wait () method is executed. Well, let's just go here. If we talk too much, it seems like the author is arrogant, and there is also suspicion of insulting the reader's Java base. Start code demonstration.
Producer-consumer model-repository source code
Package COM. defonds. thread; <br/>/** <br/> * Project name: threadapp <br/> * Class Name: godown <br/> * class description: producer-consumer model warehouse <br/> * Creator: defonds <br/> * Creation Time: 10:50:00 <br/> * modifier: defonds <br/> * modification time: 10:50:00 <br/> * remarks: <br/> * @ version <br/> */<br/> public class godown {</P> <p> private final int max_size = 100; // maximum inventory capacity <br/> private int curnum; // existing inventory </P> <p>/** <br/> * <Br/> * Create a new instance godown. <br/> * @ Param curnum <br/> */<br/> Public godown (INT curnum) {<br/> This. curnum = curnum; <br/>}</P> <p>/** <br/> * produce a specified number of products <br/> */<br/> Public synchronized void produce (int neednum) {<br/> while (true) {<br/>/** <br/> * if production is not required, enter the waiting status <br/> */<br/> while (this. curnum + neednum> This. max_size) {<br/> system. out. println (thread. currentthread (). getname () + "number of products to be produced" + Neednum + "the remaining inventory capacity has been exceeded" + (this. max_size-This. curnum) + ", production tasks cannot be performed for the moment! "); <Br/> try {<br/> This. wait (); <br/>} catch (interruptedexception e) {<br/> // todo auto-generated Catch Block <br/> E. printstacktrace (); <br/>}</P> <p>/** <br/> * meets the production conditions, production <br/> */<br/> This. curnum + = neednum; <br/> system. out. println (thread. currentthread (). getname () + "already produced" + neednum + ", the inventory is:" + this. curnum); </P> <p>/** <br/> * wake up all threads waiting on this object Monitor <br/> */<br/> This. policyall (); <br />}< Br/>}</P> <p>/** <br/> * consume a specified number of products <br/> */<br/> Public synchronized void consume (INT neednum) {<br/> while (true) {<br/>/** <br/> * if it cannot be consumed, enter the waiting status <br/> */<br/> while (this. curnum <neednum) {<br/> system. out. println (thread. currentthread (). getname () + "number of products to be consumed" + neednum + "excess inventory" + this. curnum + ", cannot be consumed now! "); <Br/> try {<br/> This. wait (); <br/>} catch (interruptedexception e) {<br/> // todo auto-generated Catch Block <br/> E. printstacktrace (); <br/>}</P> <p>/** <br/> * meets the consumption conditions, perform product consumption <br/> */<br/> This. curnum-= neednum; <br/> system. out. println (thread. currentthread (). getname () + "consumed" + neednum + ", the inventory is:" + this. curnum); </P> <p>/** <br/> * wake up all threads waiting on this object Monitor <br/> */<br/> This. policyall (); <br/>}< br/>
Producer-consumer model-producer source code
Package COM. defonds. thread; <br/>/** <br/> * Project name: threadapp <br/> * Class Name: producer <br/> * class description: producer-producer of the consumer model <br/> * Creator: defonds <br/> * Creation Time: 10:45:30 <br/> * modifier: defonds <br/> * modification time: 10:45:30 <br/> * remarks: <br/> * @ version <br/> */<br/> public class producer extends thread {</P> <p> private int neednum; // number of products to be produced each time <br/> private godown; // repository </P> <p>/** <br/> * Create a new instance producer. <br/> * @ Param neednum <br/> * @ Param godown <br/> */<br/> Public producer (INT neednum, godown) {<br/> This. neednum = neednum; <br/> This. godown = godown; <br/>}</P> <p>/** <br/> * rewrite Java. lang. thread run method <br/> */<br/> Public void run () {<br/> This. godown. produce (this. neednum); <br/>}< br/>
Producer-consumer model-consumer source code
Package COM. defonds. thread; <br/>/** <br/> * Project name: threadapp <br/> * Class Name: consumer <br/> * class description: producer-consumer model <br/> * Creator: defonds <br/> * Creation Time: 10:50:48 <br/> * modifier: defonds <br/> * modification time: 10:50:48 <br/> * remarks: <br/> * @ version <br/> */<br/> public class Consumer extends thread {</P> <p> private int neednum; // number of products to be consumed each time <br/> private godown; // repository </P> <p>/** <br/> * Create a new instance consumer. <br/> * @ Param neednum <br/> * @ Param godown <br/> */<br/> public consumer (INT neednum, godown) {<br/> This. neednum = neednum; <br/> This. godown = godown; <br/>}</P> <p>/** <br/> * rewrite Java. lang. thread run method <br/> */<br/> Public void run () {<br/> This. godown. consume (this. neednum); <br/>}< br/>
Producer-consumer model-program entry source code
Package COM. defonds. thread; <br/>/** <br/> * Project name: threadapp <br/> * Class Name: threadapp <br/> * class description: producer-consumer model program entry <br/> * Creator: defonds <br/> * Creation Time: 10:51:15 <br/> * modifier: defonds <br/> * modification time: 10:51:15 <br/> * remarks: <br/> * @ version <br/> */<br/> public class threadapp {<br/> Public static void main (string [] ARGs) {</P> <p>/** <br/> * initialize the repository <br/> */<br/> godown = new godown (30 ); </P> <p>/** <br/> * Consumer initialization <br/> */<br/> consumer consumer0 = new consumer (30, godown ); <br/> consumer consumer1 = new consumer (20, godown); <br/> consumer consumer2 = new consumer (40, godown ); </P> <p>/** <br/> * producer initialization <br/> */<br/> producer producer0 = new producer (10, godown ); <br/> producer producer1 = new producer (10, godown); <br/> producer producer2 = new producer (10, godown ); <br/> producer producer3 = new producer (10, godown); <br/> producer producer4 = new producer (10, godown ); <br/> producer producer5 = new producer (10, godown); <br/> producer producer6 = new producer (10, godown ); <br/> producer producer7 = new producer (10, godown ); </P> <p>/** <br/> * mark each producer/consumer <br/> */<br/> consumer0.setname ("consumer0 "); <br/> consumer1.setname ("consumer1"); <br/> consumer2.setname ("consumer2"); <br/> producer0.setname ("producer0 "); <br/> producer1.setname ("producer1"); <br/> producer2.setname ("producer2"); <br/> producer3.setname ("producer3 "); <br/> producer4.setname ("producer4"); <br/> producer5.setname ("producer5"); <br/> producer6.setname ("producer6 "); <br/> producer7.setname ("producer7 "); </P> <p>/** <br/> * start production-consumption <br/> */<br/> consumer0.start (); <br/> consumer1.start (); <br/> consumer2.start (); <br/> producer0.start (); <br/> producer1.start (); <br/> producer2.start (); <br/> producer3.start (); <br/> producer4.start (); <br/> producer5.start (); <br/> producer6.start (); <br/> producer7.start (); <br/>}< br/>
The console output snippet when this code is executed at one time:
Consumer2 has consumed 40, and the inventory is: 20
The number of products to be consumed by consumer2 has exceeded the remaining inventory by 20, and cannot be consumed now!
Consumer0: the number of products to be consumed 30 has exceeded the remaining inventory 20. Currently, it cannot be consumed!
Consumer1 has consumed 20 and the inventory is: 0
The number of products to be consumed by consumer1 has exceeded the remaining inventory by 0. Currently, the product cannot be consumed!
Consumer0: the number of products to be consumed 30 has exceeded the remaining inventory 0. Currently, the product cannot be consumed!
The number of products to be consumed by consumer2 has exceeded the remaining inventory by 0. Currently, the product cannot be consumed!
Producer5 has produced 10 and the inventory is: 10
Producer5 has produced 10 and the inventory is: 20
Producer5 has produced 10 and the inventory is: 30
Producer5 has produced 10 and the inventory is: 40
Producer5 has produced 10 and the inventory is: 50
Producer5 has produced 10 and the inventory is: 60
Producer5 has produced 10 and the inventory is: 70
Producer5 has produced 10 and the inventory is: 80
Producer5 has produced 10 and the inventory is: 90
Producer5 has produced 10 and the inventory is: 100
The number of products to be produced by producer5 has exceeded the remaining inventory capacity by 0. production tasks cannot be performed for the moment!
The number of products to be produced by producer1 has exceeded the remaining inventory capacity by 0. production tasks cannot be performed for the moment!
Producer0: the number of products to be produced 10 has exceeded the remaining inventory capacity 0. Currently, production tasks cannot be performed!
The number of products to be produced in producer2 has exceeded the remaining inventory capacity by 0. production tasks cannot be performed now!
The number of products to be produced in producer4 has exceeded the remaining inventory capacity by 0. production tasks cannot be performed now!
The number of products to be produced in producer3 has exceeded the remaining inventory capacity by 0. production tasks cannot be performed now!
The number of products to be produced in producer6 has exceeded the remaining inventory capacity by 0. production tasks cannot be performed now!
The number of products to be produced in producer7 has exceeded the remaining inventory capacity by 0. production tasks cannot be performed now!
Consumer2 has consumed 40, and the inventory is: 60
Consumer2 has consumed 40, and the inventory is: 20
The number of products to be consumed by consumer2 has exceeded the remaining inventory by 20, and cannot be consumed now!
Consumer0: the number of products to be consumed 30 has exceeded the remaining inventory 20. Currently, it cannot be consumed!
Consumer1 has consumed 20 and the inventory is: 0
The number of products to be consumed by consumer1 has exceeded the remaining database.
Of course, this program still has a problem, that is, once a producer obtains CPU resources and produces a product, it does not allow CPU resources even though it uses policyall, so that other producers can no longer obtain CPU resources; so can consumers. I believe that smart readers will find a better solution to this problem. However, this example is mainly used to demonstrate the interaction between threads. In this case, this example is sufficient.