• Java:SynchronousQueue同步队列


    目录

    同步队列-文档注释解读     

    双线程读写同步队列示例

    take()方法示例

     poll()方法示例


    同步队列-文档注释解读     

       SynchronousQueue同步队列,jdk8源码中的文档注释对其解释如下,

    * A {@linkplain BlockingQueue blocking queue} in which each insert
    * operation must wait for a corresponding remove operation by another
    * thread, and vice versa.  A synchronous queue does not have any
    * internal capacity, not even a capacity of one.  You cannot
    * {@code peek} at a synchronous queue because an element is only
    * present when you try to remove it; you cannot insert an element
    * (using any method) unless another thread is trying to remove it;
    * you cannot iterate as there is nothing to iterate.  The
    * head of the queue is the element that the first queued
    * inserting thread is trying to add to the queue; if there is no such
    * queued thread then no element is available for removal and
    * {@code poll()} will return {@code null}.  For purposes of other
    * {@code Collection} methods (for example {@code contains}), a
    * {@code SynchronousQueue} acts as an empty collection.  This queue
    * does not permit {@code null} elements.

    简译如下:

            (线程A)对一个同步队列(SynchronousQueue的insert-写入元素操作,必须在另一个线程B的remove-移除/读出元素之后执行。

            一个同步队列是不含内部容量的(亦即:capacity=0),因为元素element-a仅在线程B尝试remove-读出它(元素a)的瞬间存在;同样,开发者也无法使用线程A主动向同步队列insert-写入元素,除非此时存在一个线程B正在准备读取(remove)同步队列中的元素。

            (上面提到,同步队列的capacity为0,因此,)开发者无法遍历/迭代同步队列。

            同步队列的头元素,就是正在排队的第一个线程正在写入的那个元素;但是,如果不存在负责写入元素操作的线程,那么,正在等待从同步队列中读出元素的线程B,通过poll()方法读取到的元素只能是null。

            同步队列就等价于一个空的Collection集合对象,也不允许存入null-空元素。

    双线程读写同步队列示例

            如下,我们创建线程A,用于从同步队列中读出数据;创建线程B,用于从同步队列中写入数据。

    take()方法示例

            首先使用take()方法读取数据,此时,当同步队列为空时,负责读出元素的线程A就会进入长期的阻塞状态。示例代码如下,

    1. import java.util.PriorityQueue;
    2. import java.util.concurrent.SynchronousQueue;
    3. public class SynchronousQueue_Class {
    4. //properties
    5. //methods
    6. public static void main(String[] args) throws InterruptedException {
    7. //SynchronousQueue-同步队列
    8. SynchronousQueue synchronousQueue = new SynchronousQueue<>();
    9. //创建一个线程-先取出数据-take()方法-取出数据
    10. new Thread(() -> {
    11. while (true){
    12. try {
    13. Object take = synchronousQueue.take();
    14. System.out.print(Thread.currentThread().getName()+"取出数据-");
    15. System.out.println(take);
    16. } catch (InterruptedException e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. }).start();
    21. //创建一个线程-写入数据-put方法会导致线程阻塞
    22. new Thread(() -> {
    23. try {
    24. System.out.println(Thread.currentThread().getName()+"写入数据...");
    25. synchronousQueue.put("aaa");
    26. synchronousQueue.put("bbb");
    27. synchronousQueue.put("ccc");
    28. synchronousQueue.put("ddd");
    29. synchronousQueue.put("eee");
    30. } catch (InterruptedException e) {
    31. e.printStackTrace();
    32. }
    33. }).start();
    34. }
    35. }

     poll()方法示例

            其次使用poll()方法读取数据,当负责读出元素的线程A预先设定阻塞时间时,当同步队列为空时,就会在等待若干时长之后,若返回值仍然为null空,就会自动结束阻塞状态。示例代码如下,

    1. public static void main(String[] args) throws InterruptedException {
    2. poll_test();
    3. }
    4. private static void poll_test(){
    5. SynchronousQueue synchronousQueue = new SynchronousQueue<>();
    6. //线程A-poll方法-读出数据
    7. new Thread(new Runnable() {
    8. @Override
    9. public void run() {
    10. while (true){
    11. String poll = null;//阻塞5s,若返回值仍然为null,自动结束子线程A
    12. try {
    13. poll = synchronousQueue.poll(5, TimeUnit.SECONDS);
    14. if (Objects.isNull(poll))
    15. break;
    16. else
    17. System.out.println(Thread.currentThread().getName()+"读出数据:"+poll);
    18. } catch (InterruptedException e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. }
    23. }).start();
    24. //线程B-put()方法-写入数据
    25. new Thread(new Runnable() {
    26. @Override
    27. public void run() {
    28. System.out.println(Thread.currentThread().getName()+"写入数据...");
    29. try {
    30. synchronousQueue.put("aaa");
    31. synchronousQueue.put("bbb");
    32. synchronousQueue.put("ccc");
    33. synchronousQueue.put("ddd");
    34. synchronousQueue.put("eee");
    35. } catch (InterruptedException e) {
    36. e.printStackTrace();
    37. }
    38. }
    39. }).start();
    40. }

     

  • 相关阅读:
    基于飞迪RTK/INS组合导航模组的里程计发布方法
    趣味C语言——【猜数字】小游戏
    【WSL2教程】WSL迁移到非系统盘
    代码 - 账号密码加密登录(RSA加密传递AES密钥给用户,前端使用AES密钥进行加密内容给后台)
    51单片机的hello world之点灯
    java开发环境安装-202209
    使用内网穿透工具实现远程访问本地部署的Odoo企业管理系统
    使用Spark SQL读取阿里云OSS的数据
    linux 下代码检查工具部署使用
    【英雄哥六月集训】第 23天: 字典树
  • 原文地址:https://blog.csdn.net/weixin_43524214/article/details/128010011