Java使用Condition實(shí)現(xiàn)精準(zhǔn)喚醒線程詳解
Condition簡(jiǎn)要介紹
Condition是一個(gè)接口,創(chuàng)建Condition的實(shí)例不能直接new,Java為我們提供一個(gè)通過Lock類實(shí)例來調(diào)用newCondition()的方法來創(chuàng)建。Condition因素出Object監(jiān)視器方法( wait , notify和notifyAll )到不同的對(duì)象,以得到具有多個(gè)等待集的每個(gè)對(duì)象,通過將它們與使用任意的組合的效果Lock個(gè)實(shí)現(xiàn)。 如果Lock替換了synchronized方法和語句的使用,則Condition將替換Object監(jiān)視方法的使用。
條件(也稱為條件隊(duì)列或條件變量 )為一個(gè)線程提供暫停執(zhí)行(“等待”)的手段,直到另一個(gè)線程通知某個(gè)狀態(tài)條件現(xiàn)在可能為真。 由于對(duì)此共享狀態(tài)信息的訪問發(fā)生在不同的線程中,因此必須對(duì)其進(jìn)行保護(hù),因此某種形式的鎖定與該條件相關(guān)聯(lián)。 等待條件提供的關(guān)鍵屬性是它以原子方式釋放關(guān)聯(lián)的鎖并掛起當(dāng)前線程,就像Object.wait一樣。
Condition里的主要方法

使用Condition的Demo
例子1
package testJUC;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestCondition {
public static void main(String[] args) {
Product3 product = new Product3();
new Thread(()->{
for (int i = 0; i < 5; i++)
new Producer(product).getProduct();
},"工廠").start();
new Thread(()->{
for (int i = 0; i < 5; i++)
new Consumer(product).saleProduct();
},"學(xué)生").start();
}
}
class Product3 {
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private int flag = 1;//標(biāo)識(shí)符
public void getProduct() {
//加鎖
lock.lock();
try {
//使用while循環(huán),可以有效避免線程虛假喚醒
while (flag != 1) {
condition1.await();
}
flag = 2;
//喚醒saleProduct
condition2.signal();
System.out.println(Thread.currentThread().getName() + "生產(chǎn)一個(gè)產(chǎn)品");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//解鎖
lock.unlock();
}
}
public void saleProduct() {
lock.lock();
try {
while (flag != 2) {
condition2.await();
}
flag = 1;
//喚醒getProduct
condition1.signal();
System.out.println(Thread.currentThread().getName()+"消費(fèi)了一個(gè)產(chǎn)品");
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
//實(shí)體類
class Producer{
private Product3 product = null;
public Producer(Product3 product) {
this.product = product;
}
public void getProduct(){
product.getProduct();
}
}
class Consumer{
private Product3 product = null;
public Consumer(Product3 product) {
this.product = product;
}
public void saleProduct(){
product.saleProduct();
}
}
結(jié)果

例子2
package testJUC;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestCondition {
public static void main(String[] args) {
Print print = new Print();
new Thread(() -> {
for (int i = 0; i < 5; i++)
print.printA();
}).start();
new Thread(() -> {
for (int i = 0; i < 5; i++)
print.printB();
}).start();
new Thread(() -> {
for (int i = 0; i < 5; i++)
print.printC();
}).start();
}
}
class Print {
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1;
//輸出A的方法
public void printA() {
//加鎖
lock.lock();
try {
//使用while循環(huán),可以有效避免線程虛假喚醒
while (number != 1) {
condition1.await();
}
number = 2;
//喚醒輸出B的方法
condition2.signal();
System.out.println("AAA");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//解鎖
lock.unlock();
}
}
//輸出B的方法
public void printB() {
//加鎖
lock.lock();
try {
while (number != 2) {
condition2.await();
}
System.out.println("BBB");
number = 3;
//喚醒C
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//喚醒輸出C的方法
lock.unlock();
}
}
//輸出C的方法
public void printC() {
//加鎖
lock.lock();
try {
while (number != 3) {
condition3.await();
}
System.out.println("CCC");
number = 1;
//喚醒輸出A的方法
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//解鎖
lock.unlock();
}
}
}結(jié)果2

到此這篇關(guān)于Java使用Condition實(shí)現(xiàn)精準(zhǔn)喚醒線程詳解的文章就介紹到這了,更多相關(guān)Java Condition精準(zhǔn)喚醒線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring Security的Web應(yīng)用和指紋登錄實(shí)踐
這篇文章主要介紹了詳解Spring Security的Web應(yīng)用和指紋登錄實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03
Spring?Boot中使用Spring?Retry重試框架的操作方法
這篇文章主要介紹了Spring?Retry?在SpringBoot?中的應(yīng)用,介紹了RetryTemplate配置的時(shí)候,需要設(shè)置的重試策略和退避策略,需要的朋友可以參考下2022-04-04
SpringMVC獲取請(qǐng)求參數(shù)的方法詳解
這篇文章主要為大家詳細(xì)介紹了SpringMVC中獲取請(qǐng)求參數(shù)的方法,例如通過ServletAPI獲取和通過控制器方法的形參獲取請(qǐng)求參數(shù)等,需要的可以參考下2023-07-07
SpringBoot 使用 @Value 注解讀取配置文件給靜態(tài)變量賦值
這篇文章主要介紹了SpringBoot 使用 @Value 注解讀取配置文件給靜態(tài)變量賦值,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
MyBatis如何進(jìn)行雙重foreach循環(huán)
這篇文章主要介紹了MyBatis如何進(jìn)行雙重foreach循環(huán),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02

