BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会阻塞。
ArrayBlockingQueue是一个由数组支持的有界阻塞队列。在读写操作上都需要锁住整个容器,因此吞吐量与一般的实现是相似的,适合于实现“生产者消费者”模式。
LinkedBlockingQueue基于链表的阻塞队列,同ArrayBlockingQueue类似,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。
代码:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { final BlockingQueue queue = new ArrayBlockingQueue(3); //final BlockingQueue queue = new LinkedBlockingQueue(3); for(int i=0;i<2;i++){ new Thread(){ public void run(){ while(true){ try { Thread.sleep((long)(Math.random()*1000)); System.out.println(Thread.currentThread().getName() + "准备放数据!"); queue.put(1); System.out.println(Thread.currentThread().getName() + "已经放了数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } new Thread(){ public void run(){ while(true){ try { //将此处的睡眠时间分别改为100和1000,观察运行结果 Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "准备取数据!"); queue.take(); System.out.println(Thread.currentThread().getName() + "已经取走数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } }
1000:
Thread-0准备放数据! Thread-0已经放了数据,队列目前有1个数据 Thread-1准备放数据! Thread-1已经放了数据,队列目前有2个数据 Thread-2准备取数据! Thread-2已经取走数据,队列目前有1个数据 Thread-0准备放数据! Thread-0已经放了数据,队列目前有2个数据 Thread-1准备放数据! Thread-1已经放了数据,队列目前有3个数据 Thread-0准备放数据! Thread-2准备取数据! Thread-2已经取走数据,队列目前有2个数据 Thread-0已经放了数据,队列目前有3个数据 Thread-1准备放数据! Thread-0准备放数据! Thread-2准备取数据! Thread-2已经取走数据,队列目前有2个数据 Thread-1已经放了数据,队列目前有3个数据 Thread-1准备放数据! Thread-2准备取数据! Thread-2已经取走数据,队列目前有2个数据 Thread-0已经放了数据,队列目前有3个数据 Thread-0准备放数据! Thread-2准备取数据! Thread-2已经取走数据,队列目前有2个数据 Thread-1已经放了数据,队列目前有3个数据 Thread-1准备放数据! Thread-2准备取数据! Thread-2已经取走数据,队列目前有2个数据 Thread-0已经放了数据,队列目前有3个数据 Thread-0准备放数据! Thread-2准备取数据! Thread-2已经取走数据,队列目前有2个数据 Thread-1已经放了数据,队列目前有3个数据 Thread-1准备放数据! Thread-2准备取数据! Thread-0已经放了数据,队列目前有3个数据 Thread-2已经取走数据,队列目前有3个数据 Thread-0准备放数据! Thread-2准备取数据! Thread-2已经取走数据,队列目前有2个数据 Thread-1已经放了数据,队列目前有3个数据 Thread-1准备放数据! Thread-2准备取数据!