SynchronousQueue
应用于 Executors.newCachedThreadPool()
总的来说,队列同时最多只保持一个元素,但对外不可见,想要直到里面的元素是什么,必须取出来,所以peek()
是不可用的(永远返回null)。
别的blog中介绍的已经很详细了,这里就把API注释搬过来罢。
一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。不能在同步队列上进行peek,因为仅在试图要移除元素时,该元素才存在;除非另一个线程试图移除某个元素,否则也不能(使用任何方法)插入元素;也不能迭代队列,因为其中没有元素可用于迭代。队列的头是尝试添加到队列中的首个已排队插入线程的元素;如果没有这样的已排队线程,则没有可用于移除的元素并且
poll()
将会返回null。对于其他Collection方法(例如contains),SynchronousQueue 作为一个空 collection。此队列不允许 null 元素。对于正在等待的生产者和使用者线程而言,此类支持可选的公平排序策略。默认情况下不保证这种排序。但是,使用公平设置为true所构造的队列可保证线程以FIFO的顺序进行访问。
核心方法
put(E e)
添加一个非空元素,同时会阻塞住,直到另一个线程调用take()
take()
取出一个元素,如果队列为空,阻塞,直到另一个线程调用put(E e)
Transferer.transfer(E e, boolean timed, long nanos)
上面两个方法都依赖该方法进行操作,根据第一个参数判断是入列(栈)还是出列(栈),第二个参数决定是否启用超时机制,第三个参数为超时时间。
其他方法
offer(E e)
,offer(E e, long timeout, TimeUnit unit)
插入一个元素,并在指定时间内等待另一线程取走它,如果超时没有取走,则返回false。所以 offer()
要求元素在被插入的瞬间被取走,否则返回false,并且元素也会被删除。
add(E e)
基于offer(E e)
实现,所以只有当offer(E e)
返回 true的时候,它才返回 true,否则抛出异常IllegalStateException("Queue full")
element()
略.peek()
永远返回 null.
Transfer
SynchronousQueue
核心接口是 Transfer
TransferQueue
入列和出列都基于Spin
和CAS
方法
CAS & spin lock
CAS
(Compare And Set)的缩写。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。自旋锁
在Java 集合类、多线程中常见自旋锁
的实现与应用,比如:AtomicBoolean.getAndSet(boolean newValue)