最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)自定義阻塞隊列

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

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

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

1.新建一個 MyQueue.java 類

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

import com.xiaoleilu.hutool.util.StrUtil;

/**
 * 使用 notify() 和 wait() 實現(xiàn)自定義阻塞隊列
 *
 * @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. 計數(shù)器,用于判定邊界
	private AtomicInteger count = new AtomicInteger(0);
	private final int minSize = 0;

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

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

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

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

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

		return ret;
	}

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

}

2.新建一個測試類 MyQueueTest.java,測試類中,我們初始化一個隊列,并將元素填滿,然后啟動一個線程 t1,去插入數(shù)據(jù),中間休眠 2s,再去啟動一個線程 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)前隊列的長度: {}", 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.啟動測試類,查看運行結(jié)果??刂婆_如果應(yīng)該出現(xiàn)的效果是,隊列先初始化完成,然后休眠 2s,接下來先取數(shù)據(jù),再插入數(shù)據(jù),則證明阻塞隊列生效。下面是控制臺運行的效果:

  • 初始化隊列

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

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

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

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

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

相關(guān)文章

  • Java中常用的設(shè)計模式之觀察者模式詳解

    Java中常用的設(shè)計模式之觀察者模式詳解

    這篇文章主要為大家詳細(xì)介紹了Java中常用的設(shè)計模式之觀察者模式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Spring自動注入失敗的解決方法

    Spring自動注入失敗的解決方法

    這篇文章主要介紹了Spring自動注入失敗的解決方法,幫助大家更好的理解和學(xué)習(xí)使用Spring框架,感興趣的朋友可以了解下
    2021-05-05
  • 詳解Java回調(diào)的原理與實現(xiàn)

    詳解Java回調(diào)的原理與實現(xiàn)

    回調(diào)函數(shù),顧名思義,用于回調(diào)的函數(shù)?;卣{(diào)函數(shù)只是一個功能片段,由用戶按照回調(diào)函數(shù)調(diào)用約定來實現(xiàn)的一個函數(shù)?;卣{(diào)函數(shù)是一個工作流的一部分,由工作流來決定函數(shù)的調(diào)用(回調(diào))時機。
    2017-03-03
  • Java入門案列之猜拳小游戲

    Java入門案列之猜拳小游戲

    這篇文章主要為大家詳細(xì)介紹了Java入門案列之猜拳小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Java中的時間戳各種操作方法詳解

    Java中的時間戳各種操作方法詳解

    在Java中時間戳指自1970年1月1日午夜(UTC)以來的毫秒數(shù),Java提供了多種方式獲取和操作時間戳,包括System.currentTimeMillis()、java.util.Date、java.sql.Timestamp類,Java8及以后版本引入了java.time包,增強了日期時間處理能力,需要的朋友可以參考下
    2024-10-10
  • 解決Java導(dǎo)入excel大量數(shù)據(jù)出現(xiàn)內(nèi)存溢出的問題

    解決Java導(dǎo)入excel大量數(shù)據(jù)出現(xiàn)內(nèi)存溢出的問題

    今天小編就為大家分享一篇解決Java導(dǎo)入excel大量數(shù)據(jù)出現(xiàn)內(nèi)存溢出的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • 淺談HashMap、HashTable的key和value是否可為null

    淺談HashMap、HashTable的key和value是否可為null

    這篇文章主要介紹了淺談HashMap、HashTable的key和value是否可為null,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 解決java.util.HashMap$Values?cannot?be?cast?to?java.ut的問題

    解決java.util.HashMap$Values?cannot?be?cast?to?java.ut的問題

    這篇文章主要介紹了解決java.util.HashMap$Values?cannot?be?cast?to?java.ut的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 聊聊maven與jdk版本對應(yīng)關(guān)系

    聊聊maven與jdk版本對應(yīng)關(guān)系

    這篇文章主要介紹了maven與jdk版本對應(yīng)關(guān)系,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java單元測試JUnit框架原理與用法實例教程

    java單元測試JUnit框架原理與用法實例教程

    這篇文章主要介紹了java單元測試JUnit框架原理與用法,結(jié)合實例形式較為詳細(xì)的分析了java單元測試JUnit框架的概念、原理、使用方法及相關(guān)注意事項,需要的朋友可以參考下
    2017-11-11

最新評論

时尚| 稷山县| 黄山市| 灌阳县| 海盐县| 安徽省| 鄱阳县| 宁波市| 杂多县| 沅陵县| 那曲县| 枞阳县| 黑山县| 恭城| 碌曲县| 思南县| 高要市| 陵川县| 岢岚县| 江城| 北川| 大竹县| 小金县| 彭山县| 镇安县| 朔州市| 汪清县| 吴江市| 盈江县| 柞水县| 时尚| 府谷县| 崇左市| 衡阳县| 南丰县| 花莲市| 闻喜县| 叶城县| 渭源县| 分宜县| 翁牛特旗|