BlockingQueue阻塞队列详解

BlockingQueue 和 SynchronousQueue

BlockingQueue

BlockingQueue阻塞队列详解_第1张图片
BlockingQueue阻塞队列详解_第2张图片
BlockingQueue的四组API:
① add 和 remove
add(E e) :将指定的元素插入到此队列中,成功则返回true,队列满了插入失败则抛出异常java.lang.IllegalStateException: Queue full
remove() :返回并删除队首元素,如果队列为空删除失败则抛出异常java.util.NoSuchElementException
element() :返回队首元素,队列为空则抛出异常java.util.NoSuchElementException

② offer 和 poll
offer(E e) :将指定的元素插入到此队列中,成功则返回true,队列满了插入失败则返回false
poll() :返回并删除队首元素,如果队列为空删除失败则返回null
peek() :返回队首元素,队列为空则返回null

③ put 和 take
put(E e) :将指定的元素插入到此队列中,没有返回值,如果队列满了则一直等待(阻塞),直到有元素从队列中被取出
take() :返回并删除队首元素,如果队列为空则一直等待(阻塞),直到有新的元素插入队列

④ offer(E e, long timeout, TimeUnit unit) 和 poll(long timeout, TimeUnit unit)
offer(E e, long timeout, TimeUnit unit) :将指定元素插入队列中,如果队列已满则等待给定时间,如果还是无法插入则返回false并执行下一条语句
poll(long timeout, TimeUnit unit) :返回并删除队首元素,如果队列为空则等待给定时间,如果队列还是为空无元素删除则返回null并执行下一条语句

public class BlockingQueueTest {
    public static void main(String[] args) throws InterruptedException {
        test4();
    }

    public static void test1(){
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(arrayBlockingQueue.add("a")); // 将元素插入队列,插入成功返回true
        System.out.println(arrayBlockingQueue.add("b"));
        System.out.println(arrayBlockingQueue.add("c"));
        //System.out.println(arrayBlockingQueue.add("d")); // 插入失败,超出队列容量抛出异常:java.lang.IllegalStateException: Queue full

        System.out.println(arrayBlockingQueue.element()); // 返回队首元素,队列为空则抛出异常:java.util.NoSuchElementException

        System.out.println(arrayBlockingQueue.remove()); // 返回并删除队首元素
        System.out.println(arrayBlockingQueue.remove());
        System.out.println(arrayBlockingQueue.remove());
        //System.out.println(arrayBlockingQueue.remove()); // 删除失败,队列为空则抛出异常:java.util.NoSuchElementException
    }

    public static void test2(){
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(arrayBlockingQueue.offer("a")); // 将元素插入队列,插入成功返回true
        System.out.println(arrayBlockingQueue.offer("b"));
        System.out.println(arrayBlockingQueue.offer("c"));
        System.out.println(arrayBlockingQueue.offer("d")); // 插入失败,超出队列容量返回false

        System.out.println(arrayBlockingQueue.peek()); // 返回队首元素,队列为空则返回null

        System.out.println(arrayBlockingQueue.poll()); // 返回并删除队首元素
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll()); // 删除失败,队列为空返回null
    }

    public static void test3() throws InterruptedException {
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        arrayBlockingQueue.put("a"); // 将指定的元素插入到此队列中,没有返回值
        arrayBlockingQueue.put("b");
        arrayBlockingQueue.put("c");
        //arrayBlockingQueue.put("d"); // 队列满了则一直等待直到有元素从队列中取出

        System.out.println(arrayBlockingQueue.take()); // 返回并删除队首元素
        System.out.println(arrayBlockingQueue.take());
        System.out.println(arrayBlockingQueue.take());
        //System.out.println(arrayBlockingQueue.take()); // 如果队列为空则一直等待(阻塞),直到有新的元素插入队列
    }

    public static void test4() throws InterruptedException {
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        arrayBlockingQueue.offer("a");
        arrayBlockingQueue.offer("b");
        arrayBlockingQueue.offer("c");
        System.out.println(arrayBlockingQueue.offer("d", 2, TimeUnit.SECONDS)); // 当队列满了,等待2秒还是插入不了则返回false并执行下一条语句

        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll(2,TimeUnit.SECONDS)); // 当队列为空,等待2秒还是为空无元素删除则返回null并执行下一条语句
    }
}

SynchronousQueue

SynchronousQueue同步队列是BlockingQueue的实现类
同步队列没有任何内部容量,甚至没有一个容量
SynchronousQueue同步队列其中每个插入操作必须等待另一个线程相应的删除操作,反之亦然
即插入一个元素必须等待删除取出一个元素后才能再插入一个元素,取出一个元素必须等待插入一个元素后才能取出
可以把SynchronousQueue同步队列想象成容量为1的一个阻塞队列BlockingQueue
public class SynchronousQueueTest {
    public static void main(String[] args) {
        SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>();
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"插入元素 a");
                synchronousQueue.put("a");
                System.out.println(Thread.currentThread().getName()+"插入元素 b");
                synchronousQueue.put("b");
                System.out.println(Thread.currentThread().getName()+"插入元素 c");
                synchronousQueue.put("c");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();
        new Thread(()->{
            try{
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

结果:

A插入元素 a
B取出元素a
A插入元素 b
B取出元素b
A插入元素 c
B取出元素c
由于队列没有容量,因此不能调用peek操作,因为只有移除元素时才有元素

你可能感兴趣的:(线程同步,多线程)