1. 程式人生 > 實用技巧 >Java多執行緒 — — lock、await 、signal 組合 替換 sync、wait、notifyAll,實現精準喚醒執行緒

Java多執行緒 — — lock、await 、signal 組合 替換 sync、wait、notifyAll,實現精準喚醒執行緒

接上篇部落格我們使用老舊的多執行緒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遍為止。