執行緒通訊之定製化
之前文章中寫了下Condition的使用,這裡我們詳細說下其中的用法:
首先使用Condition需要例項化Lock
private Lock lock = new ReentrantLock(); //建立鎖
使用lock裡面的newCondition方法建立Condition物件:
private Condition c1 = lock.newCondition();
其優點:比synchronized更安全、更高效。
選自:廖雪峰的官網-Java教程
Condition
提供的await()
、signal()
、signalAll()
原理和synchronized
鎖物件的wait()
、notify()
、notifyAll()
是一致的,並且其行為也是一樣的:
await()
會釋放當前鎖,進入等待狀態;signal()
會喚醒某個等待執行緒;signalAll()
會喚醒所有等待執行緒;- 喚醒執行緒從
await()
返回後需要重新獲得鎖。
需要注意的是上面signal\signalAll與await方法的對應關係;
通過一個例子來理解執行緒間的定製化:
要求:
實現程式碼:
package com.JUC;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//執行緒間的定製化通訊
class ShareRewsource {
private int flag = 1; //1表示執行緒AAA,2表示執行緒BBB,3表示執行緒CCC
private Lock lock = new ReentrantLock(); //建立鎖
//代替Object中的等待、喚醒等操作,更加的安全高效
private Condition c1 = lock.newCondition(); //對標AAA執行緒
private Condition c2 = lock.newCondition(); //對標BBB執行緒
private Condition c3 = lock.newCondition(); //對標CC執行緒
//建立方法
public void print5(int loop) {
lock.lock();
try {
while (flag != 1) {
c1.await();
}
//操作
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + "-----" + i + "::" + loop);
}
flag = 2;
c2.signal(); //通知BBB執行緒 喚醒BBB執行緒,喚醒後在BBB執行緒的await後繼續執行;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//建立方法
public void print10(int loop) {
lock.lock();
try {
while (flag != 2) {
c2.await();
}
//操作
for (int i = 1; i <= 10; i++) {
System.out.println(Thread.currentThread().getName() + "-----" + i + "::" + loop);
}
flag = 3;
c3.signal(); //通知CCC執行緒
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//建立方法
public void print15(int loop) {
lock.lock();
try {
while (flag != 3) {
c3.await();
}
//操作
for (int i = 1; i <= 15; i++) {
System.out.println(Thread.currentThread().getName() + "-----" + i + "::" + loop);
}
flag = 1;
c1.signal(); //通知AAA執行緒
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class ThreadPrivateDemo {
public static void main(String[] args) {
ShareRewsource rewsource = new ShareRewsource();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
rewsource.print5(i);
}
}, "AAA").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
rewsource.print10(i);
}
}, "BBB").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
rewsource.print15(i);
}
}, "CCC").start();
}
}
其中對應關係:注意喚醒和等待所在的程式碼段
c2.signal() --> c2.await()
c3.signal() --> c3.await()
c1.signal() --> c1.await()