阻塞隊列BlockingQueue

BlockingQueue很好的解決了多線程中數據的傳輸,首先BlockingQueue是一個接口,它大致有四個實現類,這是一個很特殊的隊列,如果BlockQueue是空的,從BlockingQueue取東西的操作將會被阻斷進入等待狀態,直到BlockingQueue進了東西纔會被喚醒.同樣,如果BlockingQueue是滿的,任何試圖往裏存東西的操作也會被阻斷進入等待狀態,直到BlockingQueue裏有空間纔會被喚醒繼續操作。

BlockingQueue的四個實現類:

1.ArrayBlockingQueue:規定大小的BlockingQueue,其構造函數必須帶一個int參數來指明其大小.其所含的對象是以FIFO(先入先出)順序排序的. 
2.LinkedBlockingQueue:大小不定的BlockingQueue,若其構造函數帶一個規定大小的參數,生成的BlockingQueue有大小限制,若不帶大小參數,所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定.其所含的對象是以FIFO(先入先出)順序排序的 
3.PriorityBlockingQueue:類似於LinkedBlockQueue,但其所含對象的排序不是FIFO,而是依據對象的自然排序順序或者是構造函數的Comparator決定的順序. 
4.SynchronousQueue:特殊的BlockingQueue,對其的操作必須是放和取交替完成的. 

BlockingQueue的常用方法:

        1)add(anObject):把anObject加到BlockingQueue裏,即如果BlockingQueue可以容納,則返回true,否則報異常 
        2)offer(anObject):表示如果可能的話,將anObject加到BlockingQueue裏,即如果BlockingQueue可以容納,則返回true,否則返回false. 
        3)put(anObject):把anObject加到BlockingQueue裏,如果BlockQueue沒有空間,則調用此方法的線程被阻斷直到BlockingQueue裏面有空間再繼續. 
        4)poll(time):取走BlockingQueue裏排在首位的對象,若不能立即取出,則可以等time參數規定的時間,取不到時返回null 
      5)take():取走BlockingQueue裏排在首位的對象,若BlockingQueue爲空,阻斷進入等待狀態直到Blocking有新的對象被加入爲止 

例子:

這個例子主要模擬了生產者和消費者之間的工作流程,是一個簡單的消費者等待生產者生產產品供消費者消費的場景。

生產者:

package com.gefufeng;

import java.util.concurrent.BlockingQueue;

public class Producter implements Runnable{
	private BlockingQueue<String> blockingQueue;
	
	public Producter(BlockingQueue<String> blockingQueue){
		this.blockingQueue = blockingQueue;
	}

	@Override
	public void run() {
		try {
			blockingQueue.put("我生產的" + Thread.currentThread().getName());
			System.out.println("我生產的" + Thread.currentThread().getName());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("生產失敗");
		}
		
	}
	
	

}

消費者:

package com.gefufeng;

import java.util.concurrent.BlockingQueue;

public class Customer implements Runnable{
	private BlockingQueue<String> blockingQueue;
	
	public Customer(BlockingQueue<String> blockingQueue){
		this.blockingQueue = blockingQueue;
	}

	@Override
	public void run() {
		for(;;){
			try {
				String threadName = blockingQueue.take();
				System.out.println("取出:" + threadName);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("取出失敗");
			}
		}
	}

}

執行類:

package com.gefufeng;

import java.util.concurrent.ArrayBlockingQueue;

public class Executer {
	
	public static void main(String[] args) {
		ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<String>(2);
		Producter producter = new Producter(arrayBlockingQueue);
		Customer cusotmer = new Customer(arrayBlockingQueue);
		new Thread(cusotmer).start();
		for(;;){
			try {
				Thread.sleep(2000);
				new Thread(producter).start();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
		
	}

}

首先是消費者循環等待產品,當第一次循環時執行blockingQueue.take(),是拿不出任何產品的,於是進入阻塞狀態,兩秒後,生產者生產了一個產品,於是blockingQueue拿到產品,打印了日誌,然後消費者執行第二次循環,發現blockingQueue.take()又沒拿到產品,於是又進入阻塞狀態。。。依次循環

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章