进阶篇:同步阻塞队列之LinkedBlockingQueue(十一)

JDK为我们提供了多个阻塞队列的实现,什么是阻塞队列呢? 我们都知道队列就是一组数据的集合,而阻塞队列的意思是,当你往队列中取数据时,如果没有数据,你将被阻塞,一直等到拿到数据为止;

今天我们就来看一下比较常用的遵循先进先出的阻塞队列LinkedBlockingQueue;

//同步阻塞队列
	//可以看到,当调用take()方法去拿数据时,如果里面没有数据,将造成阻塞
	public static void blockingQueue(){
		final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
		ExecutorService exec = Executors.newCachedThreadPool();
		//一个线程不断的往队列中取东西
		exec.execute(new Runnable() {
			public void run() {
				while( !Thread.currentThread().isInterrupted() ){
					try {
						String value = queue.take();
						System.out.println("线程"+Thread.currentThread()+"拿到数据:"+value);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		});
		//一个线程不断的往队列中放东西
		exec.execute(new Runnable() {
			public void run() {
				while( !Thread.currentThread().isInterrupted() ){
					try {
						TimeUnit.MILLISECONDS.sleep(1000);
						int number = new Random().nextInt(1000);
						System.out.println("写入数据:"+number);
						queue.put(number+"");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		});
	}


简单吧!一个线程写数据,一个线程读数据,当读数据的线程调用queue.take()往队列中拿数据时,如果队列中没有数据,它就一直阻塞,直到写数据的线程通过queue.put()方法写入数据为止! 是不是比我们自己写wait()和notify()要简单好用的多呢?!


对比上一篇文章的生产者消费者的实现,如果我们采用阻塞队列来实现的话,会变成什么样子呢?我们来看一下吧!

//餐厅
class BlockingRestaurant{
	public BlockingQueue<String> queue = new LinkedBlockingQueue<>();
}

//食物消费者(顾客)
class BlockingConsumer{
	//在这家餐厅就餐
	private BlockingRestaurant res = null;
	public BlockingConsumer( BlockingRestaurant res ) {
		this.res = res;
	}
	//吃食物方法
	public void eat() throws InterruptedException{
		while( !Thread.currentThread().isInterrupted() ){
			if( res.queue.take()!=null ){
				System.out.println("开始吃食物...");
				TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));//吃食物时间
				System.out.println("食物吃完了!...");
			}
		}
	}
}

//食物提供者(厨师)
class BlockingProvider{
	//在这家餐厅工作
	private BlockingRestaurant res =  null;
	public BlockingProvider( BlockingRestaurant res ) {
		this.res = res;
	}
	
	public void fry() throws InterruptedException{//炒菜
		while( !Thread.currentThread().isInterrupted() ){
			System.out.println("开始做食物...");
			TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
			res.queue.put("一份食物");
			System.out.println("食物做完了!...");
		}
	}
}
//经典生产者与消费者演示(采用队列)
	public static void producerByQueue(){
		ExecutorService exec = Executors.newCachedThreadPool();
		BlockingRestaurant res = new BlockingRestaurant();
		final BlockingConsumer consumer = new BlockingConsumer(res);
		final BlockingProvider provider = new BlockingProvider(res);
		
		exec.execute(new Runnable() {
			public void run() {
				try {
					consumer.eat();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		
		exec.execute(new Runnable() {
			public void run() {
				try {
					provider.fry();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
	}

简单多了吧!  Ok,这就是LinkedBlockingQueue的使用方法, 后面我们会再介绍优先级队列,延时队列等等多种队列,它们将实现更有趣的功能!


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值