SynchronousQueue同步队列
0.参考
SynchronousQueue原理
SynchronousQueue源码讲解
JAVA阻塞队列
1.定义
SynchronousQueue 也是一个队列来的,但它的特别之处在于它内部没有容器,一个生产线程,当它生产产品(即put的时候),如果当前没有人想要消费产品(即当前没有线程执行take),此生产线程必须阻塞,等待一个消费线程调用take操作,take操作将会唤醒该生产线程,同时消费线程会获取生产线程的产品(即数据传递)
同步队列:传输数据,如果生产者生产的元素入队,没有队列在消费则阻塞。如果有消费者尝试消费元素,如果不存在生产者生产则阻塞。
思考:同步队列与BlockingQueue中take与put的区别?put与take的阻塞的条件?本质区别?
2.原理模型
1.原理:当调用put(A操作)或者get(B操作)时,由于队列中不存在对应相反线程队列,则将该线程自旋之后放入队列。
当有相反线程操作到来,则按照一定规则唤醒节点。
2.非公平与公平区别为:存储挂起等待的队列线程的容器是队列(公平:先进先出)还是栈(非公平:先进后出)
3.CacheThreadPoolExecutor中同步队列使用
- 思考,如下代码的执行结果。(提示offer为非阻塞,take为阻塞,put也为阻塞操作)
final SynchronousQueue<Integer> synchronousQueue = new SynchronousQueue<>();
new Thread(new Runnable() {
@Override
public void run() {
boolean offer = synchronousQueue.offer(3);
if (offer) {
System.out.println("offer 3 is okay");
} else {
System.out.println("offer 3 is fail");
}
try {
synchronousQueue.put(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("offer 4 is okay");
}
}).start();
Thread.sleep(1000);
Integer take = synchronousQueue.take();
System.out.println(take);
同步队列在缓存线程池中使用:
- 缓存线程池的原理:任务到来,有空闲线程则使用空闲线程,无空闲线程则创建。所以称之为缓存线程
- 同步队列作用
- 情况1:存在空闲线程,此时空闲线程被getTask()中的queue.poll(timeOut)或者queue.take()方法阻塞。这时加入新任务,getTask()返回结果,阻塞释放,空闲线程将获取到任务被唤醒。
- 情况2:不存在空闲线程:加入新任务,由于offer(参考上文代码)方法失败,则创建新线程来执行该task。
- 结论:线程池中的线程,存在空闲必会执行,无空闲立即创建新线程;谓之缓存。
4.SynchroneseQueue源码解析
TODO