Java concurrency: Code explanation of traditional thread-synchronous communication technology, java Communication Technology
This article focuses on the code example of the traditional thread synchronous communication technology of Java concurrency, which is described as follows.
Let's first look at a question:
There are two threads. The sub-thread executes 10 times first, then the main thread executes 5 times, then switches to the sub-thread to execute 10 times, and then the main thread executes 5 times ...... This round-trip execution is 50 times.
After reading this question, we obviously need to use inter-thread communication. First, let's analyze the idea: first, there must be two threads, and then each thread must have a round of 50 times, because each thread needs to execute a task 50 times, the main thread executes the Task 5 times, and the subthread executes the Task 10 times. Main use of inter-thread Communication Technologywait()
Method andnotify()
Method. The wait () method causes the current thread to wait and release the lock,notify()
Method to wake up a single thread waiting on this object monitor. Next, we will complete the communication problem between threads step by step.
First, do not consider the communication between the main thread and the sub-thread. First, write the tasks to be executed by each thread:
Public class TraditionalThreadCommunication {public static void main (String [] args) {// enable a subthread new Thread (new Runnable () {@ Override public void run () {for (int I = 1; I <= 50; I ++) {synchronized (TraditionalThreadCommunication. class) {// subthread task: Execute 10 times for (int j = 1; j <= 10; j ++) {System. out. println ("sub thread sequence of" + j + ", loop of" + I );}}}}}). start (); // The main method is the main thread for (int I = 1; I <= 50; I ++) {synchronized (TraditionalThreadCommunication. class) {// main thread task: Execute 5 times for (int j = 1; j <= 5; j ++) {System. out. println ("main thread sequence of" + j + ", loop of" + I );}}}}}
As shown above, each thread has 50 large loops and executes 50 tasks. The subthread executes 10 tasks and the main thread executes 5 tasks. To ensure synchronization between two threads, the synchronized synchronization code block is used and the same lock is used: the class bytecode object. This ensures thread security. But this design is not very good, just as I wrote in the deadlock in the previous section, we can put the thread task into a class, this design mode is more structured, in addition, it is easy to solve the synchronization problem by placing different thread tasks in the same class, because it is easy to use the same lock in a class. So modify the above program:
Public class TraditionalThreadCommunication {public static void main (String [] args) {Business bussiness = new Business (); // new a Thread task processing class // start a subthread new Thread (new Runnable () {@ Override public void run () {for (int I = 1; I <= 50; I ++) {bussiness. sub (I );}}}). start (); // The main method is the main thread for (int I = 1; I <= 50; I ++) {bussiness. main (I) ;}}// common data to be used (including synchronization locks) or several common methods should belong to the same class, this design exactly reflects the high clustering and program robustness. Class Business {public synchronized void sub (int I) {for (int j = 1; j <= 10; j ++) {System. out. println ("sub thread sequence of" + j + ", loop of" + I) ;}} public synchronized void main (int I) {for (int j = 1; j <= 5; j ++) {System. out. println ("main thread sequence of" + j + ", loop of" + I );}}
After this modification, the program structure is clearer and more robust, as long as the synchronized keyword is added to the two thread task methods, this lock is used. However, there is no communication between the two threads. The execution result is that the main thread executes the task 50 times cyclically and the sub-thread recycles the task 50 times. The reason is very simple because of synchronized synchronization.
Next we will continue to improve the program so that the two threads can complete the communication described in the question:
Public class TraditionalThreadCommunication {public static void main (String [] args) {Business bussiness = new Business (); // new a Thread task processing class // start a subthread new Thread (new Runnable () {@ Override public void run () {for (int I = 1; I <= 50; I ++) {bussiness. sub (I );}}}). start (); // The main method is the main thread for (int I = 1; I <= 50; I ++) {bussiness. main (I) ;}}// common data (including synchronization locks) or several common methods should be applied to the same class, this design exactly reflects the robustness of the drama and program. Class Business {private Boolean bShouldSub = true; public synchronized void sub (int I) {while (! BShouldSub) {// if it is not your turn to execute it, try {this. wait (); // the object that calls the wait () method must be consistent with the synchronized lock object. Here synchronized is in the method, so this} catch (InterruptedException e) is used) {// TODO Auto-generated catch blocke. printStackTrace () ;}}for (int j = 1; j <= 10; j ++) {System. out. println ("sub thread sequence of" + j + ", loop of" + I);} bShouldSub = false; // change the flag this. Y (); // wake up the waiting main thread} public synchronized void main (int I) {while (bShouldSub) {// if it is not your turn to execute, just sleep try {this. wait ();} catch (InterruptedException e) {// TODO Auto-generated catch blocke. printStackTrace () ;}}for (int j = 1; j <= 5; j ++) {System. out. println ("main thread sequence of" + j + ", loop of" + I);} bShouldSub = true; // change the flag this. Y (); // wake up the waiting sub-thread }}
First, let alone the specific program implementation. In terms of structure, we have already realized the advantages of this design: The main function does not need to modify anything, the logic for inter-thread synchronization and inter-thread communication is all in the Business class. Different threads in the main function only need to call the corresponding tasks in the class. This demonstrates the benefits of high clustering.
Let's take a look at the specific code. First, define a boolean variable to identify which thread should be executed. If it is not executed by a subthread, it will sleep, so naturally the main thread will be executed, after the execution is complete, the bShouldSub is modified and the sub-thread is awakened. When the sub-thread determines that the while is not satisfied, it will not sleep, and the sub-thread task will be executed. Similarly, after the main thread modified bShouldSub, when the second loop is used to execute the main thread task, the system will sleep when the while statement is satisfied, waiting for the subthread to wake up. In this way, the logic is very clear. The main thread and sub-thread will execute their respective tasks in turn. This cycle is 50 times in total.
In addition, there is a small note: it is also possible to use if to judge, but why should we use while? Because sometimes the thread will wake up falsely (just like a person's sleepwalking, obviously sleeping, and then stood up). if it is used, then it will wake up falsely, it will not return to judge if again, so it will naturally execute the task. Well, the other thread is executing. Then it will affect each other with another thread. But if it is while, it will be different. Even if the thread is falsely awake, it will judge while, but at this time another thread is executing, bShouldSub is not modified, so I went into the while and got sleep again ~ So it is safe and will not affect another thread! This is also the case in the official JDK documentation.
To sum up the inter-thread communication ~
Summary
The above is all the details about the code of the traditional thread synchronization communication technology for Java concurrency, and I hope to help you. If you are interested, you can continue to refer to other related topics on this site. If you have any shortcomings, please leave a message. Thank you for your support!