runnableTaskQueue(任务队列):用于保存等待执行的任务的阻塞队列。 可以选择以下几个阻塞队列:
BlockingQueue的几个注意点
【1】BlockingQueue 可以是限定容量的。它在任意给定时间都可以有一个remainingCapacity,超出此容量,便无法无阻塞地put 附加元素。没有任何内部容量约束的BlockingQueue 总是报告Integer.MAX_VALUE 的剩余容量。
【2】BlockingQueue 实现主要用于生产者-使用者队列,但它另外还支持Collection 接口。
【3】BlockingQueue 实现是线程安全的。
【4】BlockingQueue 实质上不 支持使用任何一种“close”或“shutdown”操作来指示不再添加任何项。
1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.
1:它是有界阻塞队列。它是数组实现的,是一个典型的“有界缓存区”。数组大小在构造函数指定,而且从此以后不可改变。
2:是它线程安全的,是阻塞的,具体参考BlockingQueue的“注意4”。
3:不接受 null 元素
4:公平性 (fairness)可以在构造函数中指定。如果为true,则按照 FIFO 顺序访问插入或移除时受阻塞线程的队列;如果为 false,则访问顺序是不确定的。
5:它实现了BlockingQueue接口。关于BlockingQueue,请参照《BlockingQueue》
6:此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选 方法。
7:其容量在构造函数中指定。容量不可以自动扩展,也没提供手动扩展的接口。
8:在JDK5/6中,LinkedBlockingQueue和ArrayBlocingQueue等对象的poll(long timeout, TimeUnit unit)存在内存泄露Leak的对象是AbstractQueuedSynchronizer.Node,
2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的
并发库中的BlockingQueue是一个比较好玩的类,顾名思义,就是阻塞队列。该类主要提供了两个方法put()和take(),前者将一个对象放到队列中,如果队列已经满了,就等待直到有空闲节点;后者从head取一个对象,如果没有对象,就等待直到有可取的对象。
3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.
1:它是无界阻塞队列,容量是无限的,它使用与类PriorityQueue相同的顺序规则。
2:它是线程安全的,是阻塞的
3:不允许使用 null 元素。
4:对于put(E o)和offer(E o, long timeout, TimeUnit unit),由于该队列是无界的,所以此方法永远不会阻塞。因此参数timeout和unit没意义,会被忽略掉。
5:iterator() 方法中所提供的迭代器并不保证以特定的顺序遍历 PriorityBlockingQueue 的元素。
如果需要有序地遍历,则应考虑使用 Arrays.sort(pq.toArray())。
6.至于使用和别的BlockingQueue(ArrayBlockingQueue,LinkedBlockingQueue)相似,可以参照它们。7:此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选 方法。
4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.(每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,)此队列不允许 null 元素。
SynchronousQueue的定义如下
public classSynchronousQueueextendsAbstractQueueimplementsBlockingQueue,Serializable
从上面可以看出,它实现BlockingQueue,所以是阻塞队列,从名字看,它又是同步的。
它模拟的功能类似于生活中一手交钱一手交货这种情形,像那种货到付款或者先付款后发货模型不适合使用SynchronousQueue。
首先要知道SynchronousQueue没有容纳元素的能力,即它的isEmpty()方法总是返回true
另外在创建SynchronousQueue时可以传递一个boolean参数来指定它是否是访问它的线程按遵守FIFO顺序处理,true表示遵守FIFO。
四种线程池各自的特点及所用到的队列
newCachedThreadPool()缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中。能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。缓存型池子通常用于执行一些生存期很短的异步型任务 。所用队列为SynchronousQueue()
newFixedThreadPool()fixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程 其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子。和cacheThreadPool不同:fixedThreadPool池线程数固定,但是0秒IDLE(无IDLE)。这也就意味着创建的线程会一直存在。所以fixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器。所用队列为LinkedBlockingQueue()
newScheduledThreadPool()调度型线程池。这个池子里的线程可以按schedule依次delay执行,或周期执行 。0秒IDLE(无IDLE)。所用队列为DelayedWorkQueue()
newSingleThreadExecutor()单例线程,任意时间池中只能有一个线程 。用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)。所用队列为LinkedBlockingQueue()