Java wait和notifyAll實(shí)現(xiàn)簡(jiǎn)單的阻塞隊(duì)列
wait,會(huì)使調(diào)用的線(xiàn)程進(jìn)入等待狀態(tài),會(huì)釋放所持有的對(duì)象鎖(調(diào)用的時(shí)候也必須先獲取到鎖,否則會(huì)拋出異常 IllegalMonitorStateException)
notifyAll、notify,會(huì)去喚醒應(yīng)當(dāng)前對(duì)象而等待的線(xiàn)程,(調(diào)用的時(shí)候也必須先獲取到鎖,否則會(huì)拋出異常 IllegalMonitorStateException)
順便也記錄一下join方法,調(diào)用join方法,會(huì)使當(dāng)前線(xiàn)程進(jìn)入等待,如果沒(méi)有設(shè)置等待時(shí)間,就會(huì)等待另一個(gè)線(xiàn)程執(zhí)行完成才返回(ps:調(diào)用join方法并不一定立刻執(zhí)行另一個(gè)線(xiàn)程,只是當(dāng)前線(xiàn)程進(jìn)入等待,然后切換下一個(gè)線(xiàn)程)
import java.util.concurrent.atomic.AtomicInteger; /** * @author lhd */ public class BlockQueue { /** * 生產(chǎn)者鎖對(duì)象 */ private final Object addLock = new Object(); /** * 消費(fèi)者鎖對(duì)象 */ private final Object deleteLock = new Object(); /** * 隊(duì)列總大小 */ private final Integer size = 30; /** * 數(shù)據(jù)存放 */ private Object[] queue = new Object[size]; /** * 存放的數(shù)量,使用AtomicInteger是因?yàn)槠胀ǖ膇nt遞增遞減操作會(huì)存在非原子性的問(wèn)題,會(huì)使數(shù)量異常 */ private AtomicInteger count = new AtomicInteger(0); /** * 生產(chǎn) * @param o 對(duì)象 */ public void add(Object o) { //獲取生產(chǎn)鎖,wait方法必須獲取到對(duì)象鎖后才可以調(diào)用,否則拋出異常 synchronized (addLock){ //判斷是否超過(guò)隊(duì)列大小,超過(guò)則進(jìn)入等待 while (count.get() >= size){ try { addLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //存放一個(gè) queue[count.get()] = o; //遞增 int i = count.incrementAndGet(); //打印一下日志 String name = Thread.currentThread().getName(); System.out.println(name + "生產(chǎn)了一個(gè),現(xiàn)有數(shù)量" + i); } //如果隊(duì)列有數(shù)據(jù),則調(diào)用notifyAll喚醒消費(fèi)者 if (count.get() >= 1){ //notifyAll、notify都需要先獲取對(duì)象鎖,否則會(huì)拋出異常 synchronized (deleteLock){ deleteLock.notifyAll(); } } } /** * 消費(fèi) * @return */ public Object poll(){ Object o; //先獲取對(duì)象鎖,和生產(chǎn)者類(lèi)似 synchronized (deleteLock){ //隊(duì)列里沒(méi)有數(shù)據(jù)則等待 while (count.get() <= 0){ try { deleteLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //獲取數(shù)據(jù) o = queue[count.get()]; //遞減 int i = count.decrementAndGet(); String name = Thread.currentThread().getName(); System.out.println(name + "消費(fèi)了一個(gè),現(xiàn)有數(shù)量" + i); } //如果隊(duì)列沒(méi)有滿(mǎn),則可以喚醒生產(chǎn)者 if (count.get() < size){ //需要先獲取到鎖 synchronized (addLock){ addLock.notifyAll(); } } return o; } /** * 簡(jiǎn)單的測(cè)試 * @param args */ public static void main(String[] args) { BlockQueue blockQueue = new BlockQueue(); Thread t1 = new Thread(()-> { while (true){ blockQueue.add(new Object()); } } ); Thread t2 = new Thread(()-> { while (true){ blockQueue.add(new Object()); } } ); Thread t3 = new Thread(()-> { while (true){ blockQueue.add(new Object()); } } ); Thread t4 = new Thread(()-> { while (true){ blockQueue.poll(); } } ); Thread t5 = new Thread(()-> { while (true){ blockQueue.poll(); } } ); Thread t6 = new Thread(()-> { while (true){ blockQueue.poll(); } } ); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); } }
效果:其實(shí)這個(gè)遞增遞減操作和打印操作也不是原子操作
依次打印線(xiàn)程1,2,3
/** * @author lhd */ public class JoinTest { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> System.out.println(1)); Thread t2 = new Thread(()-> System.out.println(2)); Thread t3 = new Thread(()-> System.out.println(3)); t1.start(); t1.join(); t2.start(); t2.join(); t3.start(); t3.join(); } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot?整合mybatis+mybatis-plus的詳細(xì)步驟
這篇文章主要介紹了SpringBoot?整合mybatis+mybatis-plus的步驟,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06SpringMVC使用JsonView針對(duì)統(tǒng)一實(shí)體返回不同信息
這篇文章主要為大家介紹了SpringMVC使用JsonView針對(duì)統(tǒng)一實(shí)體返回不同信息,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03Java設(shè)計(jì)模式之橋接模式的實(shí)現(xiàn)
今天給大家?guī)?lái)的文章是Java設(shè)計(jì)模式的相關(guān)知識(shí)點(diǎn),文中對(duì)橋接模式作了非常詳細(xì)的介紹及代碼示例,對(duì)正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下2021-06-06Spring MVC學(xué)習(xí)之DispatcherServlet請(qǐng)求處理詳析
這篇文章主要給大家介紹了關(guān)于Spring MVC學(xué)習(xí)教程之DispatcherServlet請(qǐng)求處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11Java Http請(qǐng)求傳json數(shù)據(jù)亂碼問(wèn)題的解決
這篇文章主要介紹了Java Http請(qǐng)求傳json數(shù)據(jù)亂碼問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09