月眸


阻塞队列的理解

毛毛小妖 2019-08-03 255浏览 0条评论
首页/ 正文
分享到: / / / /

一、定义

阻塞队列,顾名思义,首先,他是一个队列,而一个阻塞队列在数据结构中所起到的作用如下:

线程1向阻塞队列中添加元素,线程2向阻塞队列中移除元素

*当阻塞队列是空时,从队列中获取元素的操作将会被阻塞。

*当阻塞队列是满时,从队列中添加元素的操作将会被阻塞。

二、为什么用阻塞队列,有什么好处?

在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤醒。

那为什么需要用阻塞队列呢?

好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue给你包办了。

三、阻塞队列种类

1,ArrayBlockingQueue:由数组组成的有界阻塞队列

2,LinkedBlockingQueue:由链表组成的有界阻塞队列(但大小默认为Integer.MAX_VALUE,可认为是无界的)

3,priorityBlockingQueue:支持优先级排序的无界阻塞队列

4,DelayQueue:使用优先级队列实现的延迟无界队列

5,SynchronousQueue:不存储元素的阻塞队列,即单个元素的队列

6,LinkedTransferQueue:由链表结构组成的无界队列

7,LinkedBlockingDelay:由链表结构组成的双向阻塞队列

四、BlockingQueue核心方法

方法类型 抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e,time,unit)
移除 remove() poll() take() poll(time,unit)
检查 element() peek() 不可用 不可用

1,抛出异常:当阻塞队列满时,再往队列里add插入元素会抛出illegalStateException:Queue full;当阻塞队列为空时,再从队列里remove移除元素会抛出NoSuchElementException

2,特殊值:插入方法,成功true,失败false;移除方法,成功返回出队列的元素,队列没有元素就返回null

3,阻塞:当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产线程直到put数据或者响应中断退出;当阻塞队列空时,消费者线程试图从队列里take元素,队列会一直阻塞消费者线程直到队列可用

4,超时:当阻塞队列满时,队列会阻塞生产者线程一定时间,超时后生产者线程会退出。其实特殊值超时是同一种类型。

五、SynchronousQueue的使用

SynchronousQueue没有容量,每一个put操作必须要等待一个take操作,否则不能继续添加元素,反之亦然。

package com.sy.blockingQueue;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;

public class SynchronousDemo {

	public static void main(String[] args) {
		BlockingQueue blockingQueue = new SynchronousQueue<>();
		
		new Thread(()->{
			try {
				System.out.println(Thread.currentThread().getName()+"\t put  1");
				blockingQueue.put(1);
				
				System.out.println(Thread.currentThread().getName()+"\t put  2");
				blockingQueue.put(2);
				
				System.out.println(Thread.currentThread().getName()+"\t put  3");
				blockingQueue.put(3);
			} catch (Exception e) {
				e.printStackTrace();
			}
		},"A").start();
		
		
		new Thread(()->{
			try {
				//sleep是为了让线程暂停一会儿,能看到明显效果
				//TimeUnit.SECONDS.sleep(1);
				System.out.println(Thread.currentThread().getName()+"\t take "+blockingQueue.take());
				
				//TimeUnit.SECONDS.sleep(1);
				System.out.println(Thread.currentThread().getName()+"\t take "+blockingQueue.take());
				
				//TimeUnit.SECONDS.sleep(1);
				System.out.println(Thread.currentThread().getName()+"\t take "+blockingQueue.take());
			} catch (Exception e) {
				e.printStackTrace();
			}
		},"B").start();
	}
}

运行结果:

A	 put  1
B	 take 1
A	 put  2
B	 take 2
A	 put  3
B	 take 3

 

最后修改:2019-08-03 15:11:53 © 著作权归作者所有
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付

上一篇

发表评论

评论列表

还没有人评论哦~赶快抢占沙发吧~