Java JUC并发之阻塞队列 BlockingQueue

十、阻塞队列BlockingQueue

队列 : FIFO 遵循先进先出原则

  • 写入: 如果队列满了,就必须阻塞等待消费
  • 取出: 如果队列是空的,必须阻塞等待生产

阻塞队列 BlockingQueue : 不是新的东西

具体的家族关系:

JDK文档说明


重点使用的实现类:

  • ArrayBlockingQueue 数组
  • LinkedBlockingQueue 列表
  • SynchronousQueue 同步队列

什么情况下会使用阻塞队列?

  • 多线程
  • 线程池

如何使用队列?

BlockingQueue 有四组API :

  • 抛出异常
  • 抛出异常
  • 阻塞等待
  • 超时等待
方法 抛出异常 有返回值(不抛异常) 阻塞等待 超时等待
添加 add() offer() put() offer(e,Long,TimeUnit)
移除 remove() poll() take() poll(Long,TimeUnit)
查找队首元素 element() peek()
   /**
     * 抛出异常
     */
    public static void test1() {

        // 队列大小
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));


        System.out.println("===============");
        // java.lang.IllegalStateException 队列已满 抛出异常
        //System.out.println(blockingQueue.add("d"));

        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());


        // java.util.NoSuchElementException 抛出异常
        System.out.println(blockingQueue.remove());

    }
   /**
     * 有返回值(不抛出异常)
     */
    public static void test2() {

        // 队列大小
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));

        System.out.println(blockingQueue.offer("d")); // 返回 false
        System.out.println("========================");

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll()); // 返回null

    }
/**
 * 阻塞等待
 */
public static void test4() {

    // 队列大小
    ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

    try {
        blockingQueue.put("a");
        blockingQueue.put("b");
        blockingQueue.put("c");

        // blockingQueue.put("d"); // 队列没有位置 阻塞 直接卡死

        System.out.println("==============");

        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());

        System.out.println(blockingQueue.take()); // 阻塞
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
/**
 * 超时等待
 */
public static void test3() throws InterruptedException {

    // 队列大小
    ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

    System.out.println(blockingQueue.offer("a"));
    System.out.println(blockingQueue.offer("b"));
    System.out.println(blockingQueue.offer("c"));

    System.out.println(blockingQueue.offer("d", 2, TimeUnit.SECONDS));

    System.out.println("=============");

    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());

    System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
}

SynchronousQueue 同步队列

SynchronousQueue 同步队列并没有容量 默认为 1 !

  • 当我们往同步队列放入一个元素,必须等待该元素被取出来之后,才能继续往同步队列里面放元素

  • 和阻塞队列BlockingQueue不一样,SynchronousQueue无法存储元素

put() 之后,必须先使用take()将元素取出,否则不能再put()元素进去

package com.liu.bq;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/**
 * 同步队列
 * put()完元素之后,必须要先取出,才能继续往里面put()
 * take()
 */
public class SynchronousQueueTest {

    public static void main(String[] args) {

        BlockingQueue<String> queue = new SynchronousQueue<>();

        // put元素
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName() + " put 1");
                queue.put("1");
                TimeUnit.SECONDS.sleep(1);

                System.out.println(Thread.currentThread().getName() + " put 2");
                queue.put("2");

                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + " put 3");
                queue.put("3");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T1").start();


        // take元素
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + " take => " + queue.take());

                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + " take => " + queue.take());

                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + " take => " + queue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T2").start();
    }
}
posted @ 2021-07-15 17:18  夕立君  阅读(63)  评论(0编辑  收藏  举报