Java使用Condition實現(xiàn)精準喚醒線程詳解
Condition簡要介紹
Condition是一個接口,創(chuàng)建Condition的實例不能直接new,Java為我們提供一個通過Lock類實例來調(diào)用newCondition()的方法來創(chuàng)建。Condition因素出Object監(jiān)視器方法( wait , notify和notifyAll )到不同的對象,以得到具有多個等待集的每個對象,通過將它們與使用任意的組合的效果Lock個實現(xiàn)。 如果Lock替換了synchronized方法和語句的使用,則Condition將替換Object監(jiān)視方法的使用。
條件(也稱為條件隊列或條件變量 )為一個線程提供暫停執(zhí)行(“等待”)的手段,直到另一個線程通知某個狀態(tài)條件現(xiàn)在可能為真。 由于對此共享狀態(tài)信息的訪問發(fā)生在不同的線程中,因此必須對其進行保護,因此某種形式的鎖定與該條件相關聯(lián)。 等待條件提供的關鍵屬性是它以原子方式釋放關聯(lián)的鎖并掛起當前線程,就像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();
},"學生").start();
}
}
class Product3 {
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private int flag = 1;//標識符
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)一個產(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()+"消費了一個產(chǎn)品");
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
//實體類
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();
}
}
結果

例子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();
}
}
}結果2

到此這篇關于Java使用Condition實現(xiàn)精準喚醒線程詳解的文章就介紹到這了,更多相關Java Condition精準喚醒線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解Spring Security的Web應用和指紋登錄實踐
這篇文章主要介紹了詳解Spring Security的Web應用和指紋登錄實踐,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03
Spring?Boot中使用Spring?Retry重試框架的操作方法
這篇文章主要介紹了Spring?Retry?在SpringBoot?中的應用,介紹了RetryTemplate配置的時候,需要設置的重試策略和退避策略,需要的朋友可以參考下2022-04-04
SpringBoot 使用 @Value 注解讀取配置文件給靜態(tài)變量賦值
這篇文章主要介紹了SpringBoot 使用 @Value 注解讀取配置文件給靜態(tài)變量賦值,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11

