Java多執行緒詳解(五)------多執行緒間的通訊
阿新 • • 發佈:2020-09-19
1、常規版的生產者與消費者(synchronized,wait,notify)
1 package com.study.thread; 2 3 public class TestThread919 { 4 public static void main(String[] args) { 5 AirConditioner ac = new AirConditioner(); 6 //A,B執行緒增加空調溫度 7 new Thread(() -> { 8 for (int i = 0; i < 10; i++) {9 try { 10 ac.increament(); 11 } catch (Exception e) { 12 e.printStackTrace(); 13 } 14 } 15 }, "A").start(); 16 new Thread(() -> { 17 for (int i = 0; i < 10; i++) {18 try { 19 ac.increament(); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 }, "B").start(); 25 26 //C,D執行緒減小溫度 27 new Thread(() -> { 28 for(int i = 0; i < 10; i++) { 29 try { 30 ac.decreament(); 31 } catch (Exception e) { 32 e.printStackTrace(); 33 } 34 } 35 }, "C").start(); 36 new Thread(() -> { 37 for (int i = 0; i < 10; i++) { 38 try { 39 ac.decreament(); 40 } catch (Exception e) { 41 e.printStackTrace(); 42 } 43 } 44 }, "D").start(); 45 46 47 } 48 } 49 50 class AirConditioner {//資源類 51 private int num = 0;//num表示溫度大小 52 53 //多執行緒之間的相互通知,口訣:判斷-》幹活-》通知 54 public synchronized void increament() throws Exception {//增加一度 55 while (num != 0) {//這裡判斷不用if,用while,while可以防止虛假喚醒 56 this.wait(); 57 } 58 num++; 59 System.out.println(Thread.currentThread().getName() + "\t" + num); 60 this.notifyAll(); 61 } 62 63 public synchronized void decreament() throws Exception {//減小一度 64 while (num == 0) { 65 this.wait(); 66 } 67 num--; 68 System.out.println(Thread.currentThread().getName() + "\t" + num); 69 this.notifyAll(); 70 } 71 } 72 73 輸出列印: 74 "C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=56512:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\java-project\suanfa\out\production\juc" com.study.thread.TestThread919 75 A 1 76 C 0 77 B 1 78 C 0 79 A 1 80 C 0 81 B 1 82 C 0 83 A 1 84 C 0 85 B 1 86 C 0 87 A 1 88 C 0 89 B 1 90 D 0 91 A 1 92 C 0 93 B 1 94 D 0 95 A 1 96 C 0 97 B 1 98 D 0 99 A 1 100 C 0 101 B 1 102 D 0 103 A 1 104 D 0 105 B 1 106 D 0 107 A 1 108 D 0 109 B 1 110 D 0 111 A 1 112 D 0 113 B 1 114 D 0
2、新版的生產者與消費者(Lock,Condition,await,signal)
1 package com.study.thread; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class TestThread919 { 8 public static void main(String[] args) { 9 AirConditioner ac = new AirConditioner(); 10 //A,B執行緒增加空調溫度 11 new Thread(() -> { 12 for (int i = 0; i < 10; i++) { 13 try { 14 ac.increament(); 15 } catch (Exception e) { 16 e.printStackTrace(); 17 } 18 } 19 }, "A").start(); 20 new Thread(() -> { 21 for (int i = 0; i < 10; i++) { 22 try { 23 ac.increament(); 24 } catch (Exception e) { 25 e.printStackTrace(); 26 } 27 } 28 }, "B").start(); 29 30 //C,D執行緒減小溫度 31 new Thread(() -> { 32 for (int i = 0; i < 5; i++) { 33 try { 34 ac.decreament(); 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 } 39 }, "C").start(); 40 new Thread(() -> { 41 for (int i = 0; i < 5; i++) { 42 try { 43 ac.decreament(); 44 } catch (Exception e) { 45 e.printStackTrace(); 46 } 47 } 48 }, "D").start(); 49 50 51 } 52 } 53 54 class AirConditioner {//資源類 55 private int num = 0;//num表示溫度大小 56 private Lock l = new ReentrantLock(); 57 private Condition condition = l.newCondition(); 58 59 //多執行緒之間的相互通知,口訣:判斷-》幹活-》通知 60 // public synchronized void increament() throws Exception {//增加一度 61 // while (num != 0) {//這裡判斷不用if,用while,while可以防止虛假喚醒 62 // this.wait(); 63 // } 64 // num++; 65 // System.out.println(Thread.currentThread().getName() + "\t" + num); 66 // this.notifyAll(); 67 // } 68 // 69 // public synchronized void decreament() throws Exception {//減小一度 70 // while (num == 0) { 71 // this.wait(); 72 // } 73 // num--; 74 // System.out.println(Thread.currentThread().getName() + "\t" + num); 75 // this.notifyAll(); 76 // } 77 public void increament() throws Exception {//增加一度 78 l.lock(); 79 try { 80 while (num != 0) {//這裡判斷不用if,用while,while可以防止虛假喚醒 81 condition.await(); 82 } 83 num++; 84 System.out.println(Thread.currentThread().getName() + "\t" + num); 85 condition.signalAll(); 86 } finally { 87 l.unlock(); 88 } 89 } 90 91 public void decreament() throws Exception {//增加一度 92 l.lock(); 93 try { 94 while (num == 0) {//這裡判斷不用if,用while,while可以防止虛假喚醒 95 condition.await(); 96 } 97 num--; 98 System.out.println(Thread.currentThread().getName() + "\t" + num); 99 condition.signalAll(); 100 } finally { 101 l.unlock(); 102 } 103 } 104 } 105 106 列印輸出: 107 "C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=57081:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\java-project\suanfa\out\production\juc" com.study.thread.TestThread919 108 A 1 109 C 0 110 A 1 111 C 0 112 A 1 113 C 0 114 A 1 115 C 0 116 A 1 117 D 0 118 A 1 119 D 0 120 A 1 121 D 0 122 A 1 123 D 0 124 A 1 125 D 0 126 A 1 127 C 0 128 B 1
3、新版的生產者與消費者(Lock,Condition,await,signal) 的精準通知(較普通版的優勢)
例子:有A,B,C三個執行緒,要求A列印5次,B列印10次,C列印15次,迴圈10次
1 package com.study.thread; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class ThreadOfCondition { 8 public static void main(String[] args) { 9 PrintSourse printSourse = new PrintSourse(); 10 new Thread(() -> { 11 for (int i = 0; i < 5; i++) { 12 printSourse.print5(); 13 } 14 }, "A").start(); 15 new Thread(() -> { 16 for (int i = 0; i < 5; i++) { 17 printSourse.print10(); 18 } 19 }, "B").start(); 20 new Thread(() -> { 21 for (int i = 0; i < 5; i++) { 22 printSourse.print15(); 23 } 24 }, "C").start(); 25 } 26 } 27 28 class PrintSourse { 29 //condition實現精準通知執行緒, 30 31 private int num = 1;//標誌位,為不同的執行緒設定不同的標誌位,喚醒通知的時候用 32 private Lock lock = new ReentrantLock(); 33 private Condition condition1 = lock.newCondition(); 34 private Condition condition2 = lock.newCondition(); 35 private Condition condition3 = lock.newCondition(); 36 37 //建立3個方法,分別列印5次,10,15次 38 public void print5() { 39 lock.lock(); 40 try { 41 //判斷 42 while (num != 1) { 43 condition1.await(); 44 } 45 //幹活 46 for (int i = 1; i <= 5; i++) { 47 System.out.println(Thread.currentThread().getName() + "\t" + i); 48 } 49 //通知 50 num = 2;//修改標誌位 51 condition2.signal();//通知第二把鑰匙condition2 52 53 } catch (Exception e) { 54 e.printStackTrace(); 55 } finally { 56 lock.unlock(); 57 } 58 } 59 60 public void print10() { 61 lock.lock(); 62 try { 63 //判斷 64 while (num != 2) { 65 condition2.await(); 66 } 67 //幹活 68 for (int i = 1; i <= 10; i++) { 69 System.out.println(Thread.currentThread().getName() + "\t" + i); 70 } 71 //通知 72 num = 3;//修改標誌位 73 condition3.signal();//通知第三把鑰匙condition3 74 75 } catch (Exception e) { 76 e.printStackTrace(); 77 } finally { 78 lock.unlock(); 79 } 80 } 81 82 public void print15() { 83 lock.lock(); 84 try { 85 //判斷 86 while (num != 3) { 87 condition3.await(); 88 } 89 //幹活 90 for (int i = 1; i <= 15; i++) { 91 System.out.println(Thread.currentThread().getName() + "\t" + i); 92 } 93 //通知 94 num = 1;//修改標誌位 95 condition1.signal();//通知第一把鑰匙condition1 96 } catch (Exception e) { 97 e.printStackTrace(); 98 } finally { 99 lock.unlock(); 100 } 101 } 102 103 } 104 105 結果列印: 106 A 1 107 A 2 108 A 3 109 A 4 110 A 5 111 B 1 112 B 2 113 B 3 114 B 4 115 B 5 116 B 6 117 B 7 118 B 8 119 B 9 120 B 10 121 C 1 122 C 2 123 C 3 124 C 4 125 C 5 126 C 6 127 C 7 128 C 8 129 C 9 130 C 10 131 C 11 132 C 12 133 C 13 134 C 14 135 C 15