Java多线程BlockingQueue

  BlockingQueue接口是Queue的子接口,但它的主要用途不是作为容器,而是作为线程同步的工具。BlockingQueue具有一个特征:当生产者线程试图向BlockingQueue中放入元素时,如果该队列已满,则该线程被阻塞;当消费者线程试图从BlockingQueue中取出元素时,如果该队列已空,则该线程被阻塞。BlockingQueue提供如下两个支持阻塞的方法:

  • void put(E e) :将指定元素插入此队列中,将等待可用的空间
  • E take() :获取并移除此队列的头部,在元素变得可用之前一直等待
  BlockingQueue是Queue的子接口,同样可以使用Queue接口中的方法,但方法调用之间有些区别,如下表所示:

  BlockingQueue有5个具体的实现类,根据不同需求,选择不同的实现类:

  • ArrayBlockingQueue:规定大小的BlockingQueue,基于数组实现,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的;
  • LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的;
  • PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序;当取出队头元素时,是取出队列中最小的元素。
  • SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的;
  • DelayQueue:要求集合元素都实现Delay接口,(该接口中只有一个long getDelay(TimeUnit unit):返回与此对象相关的剩余延迟时间,以给定的时间单位表示)。但Delay接口实现了Comparable接口,因此还需实现int compareTo()方法。DelayQueue根据集合元素的getDelay()方法的返回值进行排序,该队列的头部 是延迟期满后保存时间最长的 Delayed 元素,当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于等于 0 的值时,将发生到期。只有在延迟期满时才能从中提取元素,每次取出的队头元素是到期后存在时间最久的元素。

  下面是一个阻塞队列的用法:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

class Bread implements Comparable<Bread>{
	String cooker;
	long makeTime;
	public Bread(String cooker,long makeTime) {
		this.cooker = cooker;
		this.makeTime = makeTime;
	}
	@Override
	public int compareTo(Bread bread) {
		if(makeTime>bread.makeTime) return 1;
		else if(makeTime<bread.makeTime) return -1;
		else return 0;
	}
}

class Producer implements Runnable{
	private BlockingQueue<Bread> q;
	String cooker;
	private long makeTime;
	public Producer(BlockingQueue<Bread> q,String cooker) {
		this.q = q;
		this.cooker = cooker;
	}
	@Override
	public void run() {
		for(int i=0;i<3;i++){
			Bread bread = new Bread(cooker,makeTime=System.nanoTime());
			try {
				q.put(bread);
				System.out.println(cooker+" makes one piece of bread at "+makeTime);
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class Consumer implements Runnable{
	private BlockingQueue<Bread> q;
	String consumer;
	public Consumer(BlockingQueue<Bread> q,String consumer) {
		this.q = q;
		this.consumer = consumer;
	}
	@Override
	public void run() {
		for(int i=0;i<2;i++){
			try {
				Bread bread = q.take();
				System.out.println(consumer+" buys the bread made by "+bread.cooker
						+" at "+System.nanoTime());
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
}

public class BlockingQueueTest {

	public static void main(String[] args) {
		BlockingQueue<Bread> queue = new PriorityBlockingQueue<Bread>(2);
		for(int i=0;i<2;i++){
			new Thread(new Producer(queue, "cooker"+i)).start();
		}
		for(int i=0;i<3;i++){
			new Thread(new Consumer(queue, "consumer"+i)).start();
		}
		//System.out.println("Remaining "+queue.size()+" pieces of bread");
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值