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方法和語(yǔ)句的使用,則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)文章
java中double強(qiáng)制轉(zhuǎn)換int引發(fā)的OOM問題記錄
這篇文章主要介紹了java中double強(qiáng)制轉(zhuǎn)換int引發(fā)的OOM問題記錄,本文給大家分享問題排查過程,感興趣的朋友跟隨小編一起看看吧2024-10-10java隨機(jī)生成8位數(shù)授權(quán)碼的實(shí)例
下面小編就為大家?guī)硪黄猨ava隨機(jī)生成8位數(shù)授權(quán)碼的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02SpringBoot+WebSocket實(shí)現(xiàn)即時(shí)通訊功能(Spring方式)
今天給大家分享一個(gè)SpringBoot+WebSocket實(shí)現(xiàn)即時(shí)通訊功能(Spring方式),WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議,文章通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10SpringBoot 枚舉類型的自動(dòng)轉(zhuǎn)換的實(shí)現(xiàn)
一般我們?cè)跀?shù)據(jù)庫(kù)都會(huì)定義數(shù)值型的枚舉常量,不管是序列化還是反序列化都是需要我們手動(dòng)去轉(zhuǎn)換成枚舉類型的,本文主要介紹了Spring Boot 枚舉類型的自動(dòng)轉(zhuǎn)換,感興趣的可以了解一下2022-03-03