BlockingQueue阻塞队列

BlockingQueue

  • 实现类

  • Collection->Queue->BlockingQueue
  • 使用场景:多线程并发处理,线程池
  • Queue源码
public interface Queue<E> extends Collection<E> {
    boolean add(E e);
    boolean offer(E e);
    E remove();
    E poll();
    E element();
    E peek();
}
  • BlockingQueue源码
public interface BlockingQueue<E> extends Queue<E> {
    boolean add(E e);
    boolean offer(E e);
    void put(E e) throws InterruptedException;
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;
    E take() throws InterruptedException;
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;
    int remainingCapacity();
    boolean remove(Object o);
    boolean contains(Object o);
    int drainTo(Collection<? super E> c);
    int drainTo(Collection<? super E> c, int maxElements);
}

ArrayBlockingQueue

  • 依赖AQS实现并发操作
  • 四组API
方式 抛出异常 不抛出异常 阻塞等待 超时等待
添加 add(o) offer(o) put(o) offer(o, timeout, timeunit)
移除 remove() poll() take() poll(timeout, timeunit)
判断队首 element() peek() --- ---
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

class MyBlockingQueue {
    public static void main(String[] args) throws InterruptedException {

        // 抛出异常
//        test1();

        // 不抛出异常
//        test2();

        // 阻塞等待
//        test3();

        // 超时等待
        test4();
    }

    public static void test1() {
        // 队列大小
        ArrayBlockingQueue<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
        System.out.println(arrayBlockingQueue.add("a")); // true
        System.out.println(arrayBlockingQueue.add("b")); // true
        System.out.println(arrayBlockingQueue.add("c")); // true
//        System.out.println(arrayBlockingQueue.add("d")); // IllegalStateException队列满

        System.out.println(arrayBlockingQueue.element()); // 查看队首

        System.out.println(arrayBlockingQueue.remove()); // ture
        System.out.println(arrayBlockingQueue.remove()); // ture
        System.out.println(arrayBlockingQueue.remove()); // ture
//        System.out.println(arrayBlockingQueue.remove()); // NoSuchElementException
    }

    public static void test2() {
        // 队列大小
        ArrayBlockingQueue<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
        System.out.println(arrayBlockingQueue.offer("a"));
        System.out.println(arrayBlockingQueue.offer("b"));
        System.out.println(arrayBlockingQueue.offer("c"));
        System.out.println(arrayBlockingQueue.offer("d")); // 不跑出异常,返回false

        System.out.println(arrayBlockingQueue.peek());

        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<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        // 没有返回值
        arrayBlockingQueue.put("a");
        arrayBlockingQueue.put("b");
        arrayBlockingQueue.put("c");
//        arrayBlockingQueue.put("d");// 会一直等

        System.out.println(arrayBlockingQueue.take()); // a
        System.out.println(arrayBlockingQueue.take()); // b
        System.out.println(arrayBlockingQueue.take()); // c
//        System.out.println(arrayBlockingQueue.take());// 会一直等
    }

    public static void test4() throws InterruptedException {
        // 队列大小
        ArrayBlockingQueue<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
        arrayBlockingQueue.offer("a");
        arrayBlockingQueue.offer("b");
        arrayBlockingQueue.offer("c");
        arrayBlockingQueue.offer("d", 2, TimeUnit.SECONDS);// 两秒后结束等待

        System.out.println(arrayBlockingQueue.poll()); // a
        System.out.println(arrayBlockingQueue.poll()); // b
        System.out.println(arrayBlockingQueue.poll()); // c
        System.out.println(arrayBlockingQueue.poll(2, TimeUnit.SECONDS)); // 两秒后结束等待,返回null
        System.out.println("over");
    }
}

SynchronousQueue同步队列

  • 使用CAS实现线程的安全访问

  • 构造函数,默认非公平

public SynchronousQueue() {
    this(false);
}

public SynchronousQueue(boolean fair) {
    // 公平:队尾匹配队头出队
    // 非公平:先入栈后匹配
    transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}
  • 它一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

class MySynchronousQueue {
    public static void main(String[] args) {
        // 同步队列
        BlockingQueue<String> blockingQueue = new SynchronousQueue<>();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + " put\t1");
                //  往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走
                blockingQueue.put("1");
                System.out.println(Thread.currentThread().getName() + " put\t2");
                blockingQueue.put("2");
                System.out.println(Thread.currentThread().getName() + " put\t3");
                blockingQueue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Producer").start();

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                // 取出并删除element,取不到东西他会一直等
                System.out.println(Thread.currentThread().getName() + " take\t" +blockingQueue.take());
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + " take\t" +blockingQueue.take());
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + " take\t" +blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Consumer").start();
    }
}

LinkedBlockingQueue

  • 构造函数Integer.MAX_VALUE
// 默认容量
public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

public LinkedBlockingQueue(int capacity) {
    if (capacity <= 0) throw new IllegalArgumentException();
    this.capacity = capacity;
    last = head = new Node<E>(null);
}

PriorityBlockingQueue

  • 带优先级的无界阻塞队列
  • 每次出队都返回优先级最高的元素,是二叉树最小堆的实现
posted @ 2021-10-30 17:35  n1ce2cv  阅读(49)  评论(0编辑  收藏  举报