日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java阻塞队列作用_简单理解阻塞队列(BlockingQueue)中的take/put方法以及Condition存在的作用...

發(fā)布時間:2023/12/4 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java阻塞队列作用_简单理解阻塞队列(BlockingQueue)中的take/put方法以及Condition存在的作用... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

簡單理解阻塞隊列(BlockingQueue)中的take/put方法以及Condition存在的作用

Condition:可以理解成一把鎖的一個鑰匙,它既可以解鎖(通知放行),又可以加鎖(阻塞)

notFull:當(dāng)隊列元素滿了時,阻塞生產(chǎn),當(dāng)隊列元素存在元素但是沒有滿時,去通知消費

notEmpty:當(dāng)隊列中不存在元素時,阻塞消費,當(dāng)隊列元素存在元素時,去通知生產(chǎn)

while (count >= datas.length) {...}

while (count <= 0) {...}

兩個while循環(huán)判斷,而不用if,是因為線程不安全,

導(dǎo)致多線程場景下每個線程獲取到的循環(huán)條件count的值存在差異,

導(dǎo)致代碼執(zhí)行異常,用while可以使當(dāng)前線程重新刷新判斷條件count的值。

用處:

ThreadPoolExecutor中使用到了阻塞隊列,阻塞隊列中又使用到了ReentrantLock,而ReentrantLock基于AQS。

package com.zhuyz.foundation.juc;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class MyArrayBlockingQueue {

// 數(shù)組元素

private T[] datas;

// 實際的元素個數(shù)(也有索引下標(biāo)的作用)

private volatile int count;

private final ReentrantLock putLock = new ReentrantLock();

private final ReentrantLock takeLock = new ReentrantLock();

// 通知消費,暫停生產(chǎn)【當(dāng)數(shù)組full時await(put時),當(dāng)數(shù)組notFull時signal(take時)】

private Condition notFull = putLock.newCondition();

// 通知生產(chǎn),暫停消費【當(dāng)數(shù)組empty時await(take時),當(dāng)數(shù)組notEmpty時signal(put時)】

private Condition notEmpty = takeLock.newCondition();

public MyArrayBlockingQueue(int cap) {

this.datas = (T[]) new Object[cap];

}

private void put(T t) {

final ReentrantLock putLock = this.putLock;

putLock.lock();

try {

// 線程不安全,需要循環(huán)判斷,插入值之前判斷一下數(shù)組長度是否達(dá)到最大長度

while (count >= datas.length) {

System.out.println("datas is full, please waiting take");

notFull.await();

}

datas[count++] = t;

System.out.println("put: " + t);

} catch (Exception e) {

System.out.println("異常" + e);

} finally {

putLock.unlock();

}

// 通知獲取元素的線程繼續(xù)執(zhí)行(take_thread)

final ReentrantLock takeLock = this.takeLock;

takeLock.lock();

try {

notEmpty.signal();

} finally {

takeLock.unlock();

}

}

private T take() {

final ReentrantLock takeLock = this.takeLock;

takeLock.lock();

T t = null;

try {

// 線程不安全,需要循環(huán)判斷,插入值之前判斷一下數(shù)組中元素個數(shù)是否為0

while (count <= 0) {

System.out.println("datas is empty, please waiting put");

notEmpty.await();

}

// 獲取元素

t = datas[--count];

System.out.println("take: " + t);

} catch (Exception e) {

System.out.println("異常" + e);

} finally {

takeLock.unlock();

}

final ReentrantLock putLock = this.putLock;

putLock.lock();

try {

// 通知插入元素的線程繼續(xù)執(zhí)行(put_thread)

notFull.signal();

} finally {

putLock.unlock();

}

return t;

}

public static void main(String[] args) throws InterruptedException {

MyArrayBlockingQueue myArrayBlockingQueue = new MyArrayBlockingQueue<>(5);

for (int i = 0; i < 10; i++) {

int finalI = i;

new Thread(() -> myArrayBlockingQueue.put(finalI)).start();

}

TimeUnit.SECONDS.sleep(5L);

for (int i = 0; i < 5; i++) {

new Thread(() -> myArrayBlockingQueue.take()).start();

}

}

}

結(jié)果如下:

從結(jié)果中可以看出,先put了5個元素,然后另外五個元素被阻塞住了,沒有進(jìn)去

take消費5個之后,另外五個被阻塞的元素就被put進(jìn)去了

put: 0

put: 1

put: 2

put: 3

put: 4

datas is full, please waiting take

datas is full, please waiting take

datas is full, please waiting take

datas is full, please waiting take

datas is full, please waiting take

take: 4

put: 5

take: 5

take: 3

put: 6

put: 7

take: 7

put: 8

take: 8

put: 9

本文地址:https://blog.csdn.net/qq_43128724/article/details/110438987

如您對本文有疑問或者有任何想說的,請點擊進(jìn)行留言回復(fù),萬千網(wǎng)友為您解惑!

總結(jié)

以上是生活随笔為你收集整理的java阻塞队列作用_简单理解阻塞队列(BlockingQueue)中的take/put方法以及Condition存在的作用...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。