Java多執行緒 — — lock、await 、signal 組合 替換 sync、wait、notifyAll,實現精準喚醒執行緒
阿新 • • 發佈:2020-12-20
接上篇部落格我們使用老舊的多執行緒API實現了執行緒間通訊,
但是為了讓執行緒執行的更有效率,
本篇我們採用lock、await 、signal 新特性,
進行再次釀造,
舊瓶子,裝點新酒。
需求:
很簡單,要求順次列印1次A,2次B,3次C,迴圈來10遍。
廢話不多說,直接上原始碼:
package ldk.test; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /*** @Author: ldk * @Date: 2020/12/18 16:03 * @Describe: */ public class ThreadTest1 { public static void main(String[] args) { Data data = new Data(); //生產者執行緒A new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.print1(); }catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); //生產者執行緒B new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.print2(); } catch(InterruptedException e) { e.printStackTrace(); } } }, "B").start(); //消費者執行緒C new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.print3(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C").start(); } //資料類 static class Data { //表示資料個數 private int number = 1; private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); public void print1() throws InterruptedException { lock.lock(); try { while (number != 1) { condition1.await(); } System.out.println(Thread.currentThread().getName()); number = 2; condition2.signal(); } finally { lock.unlock(); } } public void print2() throws InterruptedException { lock.lock(); try { while (number != 2) { condition2.await(); } for (int i = 0; i < 2; i++) { System.out.println(Thread.currentThread().getName()); } number = 3; condition3.signal(); } finally { lock.unlock(); } } public void print3() throws InterruptedException { lock.lock(); try { while (number != 3) { condition3.await(); } for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName()); } number = 1; condition1.signal(); } finally { lock.unlock(); } } } }
執行結果:
簡單分析:
需求很明瞭,
按順序走10遍,
我們主要優化的是精準喚醒,
每次執行完須定向地執行下個目標,
lock和unlock想必大家很熟悉,就是上鎖,解鎖操作,
主要是condition控制了執行緒的精準排程
流程簡單分析:
1、值初始化為1,很自然進入print1,列印1次
2、值變成2,喚醒condition2,執行列印2次,喚醒condition3(即使開始是condition3搶到,現在值為2,condition3執行緒只能等待,最終還是有condition2執行)
3、此時值為3,且condition3喚醒,列印3次,值設定為1,喚醒condition1,
4、...周而復始,列印10遍為止。