亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java實(shí)現(xiàn)自定義阻塞隊(duì)列

 更新時(shí)間:2020年10月12日 10:08:40   作者:CodingDiary  
這篇文章主要介紹了Java如何實(shí)現(xiàn)自定義阻塞隊(duì)列,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下

今天重溫了下 java 多線程中的 notify() 方法以及 wait() 方法,一時(shí)興起,決定通過(guò)這倆個(gè)方法,實(shí)現(xiàn)一個(gè)簡(jiǎn)易的自定義阻塞隊(duì)列。

阻塞隊(duì)列是什么,與普通隊(duì)列的區(qū)別是什么?
阻塞隊(duì)列與普通隊(duì)列的區(qū)別在于,當(dāng)隊(duì)列是空的時(shí),從隊(duì)列中獲取元素的操作將會(huì)被阻塞,或者當(dāng)隊(duì)列是滿時(shí),往隊(duì)列里添加元素的操作會(huì)被阻塞。試圖從空的阻塞隊(duì)列中獲取元素的線程將會(huì)被阻塞,直到其他的線程往空的隊(duì)列插入新的元素。同樣,試圖往已滿的阻塞隊(duì)列中添加新元素的線程同樣也會(huì)被阻塞,直到其他的線程使隊(duì)列重新變得空閑起來(lái)。

1.新建一個(gè) MyQueue.java 類

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;

import com.xiaoleilu.hutool.util.StrUtil;

/**
 * 使用 notify() 和 wait() 實(shí)現(xiàn)自定義阻塞隊(duì)列
 *
 * @author Yangkai.Shen
 * @version 1.0
 * @date 2017.08.02 at 11:51:14
 */
public class MyQueue {

	// 1. 承載數(shù)據(jù)的容器
	private LinkedList<Object> queue = new LinkedList<Object>();

	// 2. 計(jì)數(shù)器,用于判定邊界
	private AtomicInteger count = new AtomicInteger(0);
	private final int minSize = 0;

	// 3. 初始化一個(gè)對(duì)象,用于加鎖
	private final Object lock = new Object();
	private final int maxSize;

	public MyQueue(int maxSize) {
		this.maxSize = maxSize;
	}

	/**
	 * 添加一個(gè)元素到隊(duì)列中,如果隊(duì)列元素已滿,則調(diào)用此方法的線程被阻塞,直到存在多余空間了,再進(jìn)行添加
	 *
	 * @param obj 添加 obj 到隊(duì)列尾部
	 */
	public void put(Object obj) {
		synchronized (lock) {
			// 1.沒(méi)有多余空間,就阻塞線程
			while (count.get() == this.maxSize) {
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			// 2.添加元素
			queue.add(obj);
			// 3.計(jì)數(shù)器累加
			count.incrementAndGet();
			System.out.println(StrUtil.format("新加入的元素為:{}", obj));
			// 4.喚醒其他線程(若本來(lái)元素為空,有線程調(diào)用 get 方法,那么原本被阻塞的,需要在此時(shí)被喚醒)
			lock.notify();
		}
	}

	/**
	 * 獲取一個(gè)元素,如果隊(duì)列元素為空,則調(diào)用此方法的線程被阻塞,直到添加新元素了,再進(jìn)行獲取
	 *
	 * @return 返回隊(duì)列的第一個(gè)元素
	 */
	public Object get() {
		Object ret = null;

		synchronized (lock) {
			// 1.沒(méi)有元素,就阻塞線程
			while (count.get() == this.minSize) {
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			// 2.取第一個(gè)元素
			ret = queue.removeFirst();
			// 3.計(jì)數(shù)器遞減
			count.decrementAndGet();
			System.out.println(StrUtil.format("移除的元素為:{}", ret));
			// 4.喚醒其他線程(若元素本來(lái)已滿,有線程調(diào)用 put 方法,那么原本被阻塞的,需要在此時(shí)被喚醒)
			lock.notify();
		}

		return ret;
	}

	public int getSize() {
		return this.count.get();
	}

}

2.新建一個(gè)測(cè)試類 MyQueueTest.java,測(cè)試類中,我們初始化一個(gè)隊(duì)列,并將元素填滿,然后啟動(dòng)一個(gè)線程 t1,去插入數(shù)據(jù),中間休眠 2s,再去啟動(dòng)一個(gè)線程 t2 取數(shù)據(jù)。

import com.xiaoleilu.hutool.util.StrUtil;

import java.util.concurrent.TimeUnit;

public class MyQueueTest {
	public static void main(String[] args) {
		final MyQueue queue = new MyQueue(5);

		queue.put("a");
		queue.put("b");
		queue.put("c");
		queue.put("d");
		queue.put("e");

		System.out.println(StrUtil.format("當(dāng)前隊(duì)列的長(zhǎng)度: {}", queue.getSize()));
		Thread t1 = new Thread(() -> {
			queue.put("f");
			queue.put("g");
			queue.put("h");
		}, "t1");
 Thread t2 = new Thread(() -> {
  queue.get();
  queue.get();
 });

 t1.start();
 try {
  TimeUnit.SECONDS.sleep(2);
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 t2.start();
}

3.啟動(dòng)測(cè)試類,查看運(yùn)行結(jié)果。控制臺(tái)如果應(yīng)該出現(xiàn)的效果是,隊(duì)列先初始化完成,然后休眠 2s,接下來(lái)先取數(shù)據(jù),再插入數(shù)據(jù),則證明阻塞隊(duì)列生效。下面是控制臺(tái)運(yùn)行的效果:

  • 初始化隊(duì)列

  • 休眠 2s 后取隊(duì)首元素,再插入隊(duì)尾元素

  • 此時(shí)我們會(huì)發(fā)現(xiàn),程序還未停止,因?yàn)榇藭r(shí)隊(duì)列已滿,但是線程 t1 還未插入 h 元素,因此線程被阻塞著,直至下次隊(duì)列有空余空間才會(huì)被喚醒。

4.至此,一個(gè)自定義阻塞隊(duì)列就已經(jīng)實(shí)現(xiàn)了。

5.細(xì)心的朋友會(huì)發(fā)現(xiàn),我打印的 log 里用到了一個(gè) StrUtil.format() 方法,這個(gè)和 slf4j 的 log 用法一致,可以使用占位符。這個(gè)是用到了一個(gè)國(guó)產(chǎn)良心工具類,hutool,國(guó)產(chǎn)開(kāi)源,需要大家的支持,覺(jué)得好用的話,期望可以去 碼云 或者 github 上給個(gè) Star 吧!

以上就是Java實(shí)現(xiàn)自定義阻塞隊(duì)列的詳細(xì)內(nèi)容,更多關(guān)于Java 自定義阻塞隊(duì)列的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringCloudGateway開(kāi)發(fā)過(guò)程解析

    SpringCloudGateway開(kāi)發(fā)過(guò)程解析

    這篇文章主要介紹了SpringCloudGateway開(kāi)發(fā)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • hibernate的分頁(yè)模糊查詢功能

    hibernate的分頁(yè)模糊查詢功能

    在web項(xiàng)目中,顯示數(shù)據(jù)一般采用分頁(yè)顯示的,在分頁(yè)的同時(shí),用戶可能還有搜索的需求,也就是模糊查詢,所以,我們要在dao寫一個(gè)可以分頁(yè)并且可以動(dòng)態(tài)加條件查詢的方法。接下來(lái)通過(guò)本文給大家介紹下
    2017-02-02
  • MyBatis加解密插件的示例詳解

    MyBatis加解密插件的示例詳解

    本文介紹了使用?MyBatis?插件實(shí)現(xiàn)數(shù)據(jù)庫(kù)字段加解密的探索過(guò)程,實(shí)際開(kāi)發(fā)過(guò)程中需要注意的細(xì)節(jié)比較多,整個(gè)流程下來(lái)我對(duì)?MyBatis?的理解也加深了,對(duì)MyBatis加解密插件感興趣的朋友跟隨小編一起看看吧
    2022-08-08
  • Java實(shí)現(xiàn)對(duì)兩個(gè)List快速去重并排序操作示例

    Java實(shí)現(xiàn)對(duì)兩個(gè)List快速去重并排序操作示例

    這篇文章主要介紹了Java實(shí)現(xiàn)對(duì)兩個(gè)List快速去重并排序操作,結(jié)合實(shí)例形式較為詳細(xì)的分析了Java針對(duì)list的遍歷、去重、排序相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2018-07-07
  • java api返回值的標(biāo)準(zhǔn)化詳解

    java api返回值的標(biāo)準(zhǔn)化詳解

    這篇文章主要介紹了java api返回值的標(biāo)準(zhǔn)化詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • java 通過(guò)聚合查詢實(shí)現(xiàn)elasticsearch的group by后的數(shù)量

    java 通過(guò)聚合查詢實(shí)現(xiàn)elasticsearch的group by后的數(shù)量

    這篇文章主要介紹了java 通過(guò)聚合查詢實(shí)現(xiàn)elasticsearch的group by后的數(shù)量,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • Java實(shí)現(xiàn)格式化打印慢SQL日志的方法詳解

    Java實(shí)現(xiàn)格式化打印慢SQL日志的方法詳解

    不管我們使用何種語(yǔ)言開(kāi)發(fā),一旦程序發(fā)生異常,日志是一個(gè)很重要的數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)格式化打印慢SQL日志的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    這篇文章主要介紹了Java中Double保留后小數(shù)位的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • IDEA:Git stash 暫存分支修改的實(shí)現(xiàn)代碼

    IDEA:Git stash 暫存分支修改的實(shí)現(xiàn)代碼

    這篇文章主要介紹了IDEA:Git stash 暫存分支修改的實(shí)現(xiàn)代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • Java使用JavaMail API發(fā)送和接收郵件的代碼示例

    Java使用JavaMail API發(fā)送和接收郵件的代碼示例

    JavaMail是Oracle甲骨文開(kāi)發(fā)的Java郵件類API,支持多種郵件協(xié)議,這里我們就來(lái)看一下Java使用JavaMail API發(fā)送和接收郵件的代碼示例
    2016-06-06

最新評(píng)論