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
* <em>head</em> 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就会进入长期的阻塞状态。示例代码如下,

import java.util.PriorityQueue;
import java.util.concurrent.SynchronousQueue;


public class SynchronousQueue_Class {
    //properties

    //methods
    public static void main(String[] args) throws InterruptedException {
        //SynchronousQueue-同步队列
        SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>();
        //创建一个线程-先取出数据-take()方法-取出数据
        new Thread(() -> {
            while (true){
                try {
                    Object take = synchronousQueue.take();
                    System.out.print(Thread.currentThread().getName()+"取出数据-");
                    System.out.println(take);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //创建一个线程-写入数据-put方法会导致线程阻塞
        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName()+"写入数据...");
                synchronousQueue.put("aaa");
                synchronousQueue.put("bbb");
                synchronousQueue.put("ccc");
                synchronousQueue.put("ddd");
                synchronousQueue.put("eee");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

 poll()方法示例

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

 public static void main(String[] args) throws InterruptedException {
        poll_test();
    }

    private static void poll_test(){
        SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>();
        //线程A-poll方法-读出数据
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    String poll = null;//阻塞5s,若返回值仍然为null,自动结束子线程A
                    try {
                        poll = synchronousQueue.poll(5, TimeUnit.SECONDS);
                        if (Objects.isNull(poll))
                            break;
                        else
                            System.out.println(Thread.currentThread().getName()+"读出数据:"+poll);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        //线程B-put()方法-写入数据
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"写入数据...");
                try {
                    synchronousQueue.put("aaa");
                    synchronousQueue.put("bbb");
                    synchronousQueue.put("ccc");
                    synchronousQueue.put("ddd");
                    synchronousQueue.put("eee");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是席木木啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值