一、什么是阻塞队列

        从名字可以看出阻塞队列是队列的一种,是一种FIFO(先进先出)的数据结构,与普通队列不同的是,它支持阻塞添加和阻塞删除

阻塞添加:当队列已满时,往队列中添加元素会阻塞等待

阻塞删除:当队列为空时,往队列中删除或获取元素将被阻塞

二、阻塞队列的四组API

方式抛出异常 不会抛出异常,有返回值 阻塞等待 超时等待
添加add()offer()put()offer(e,timeout,TimeUnit)
移除remove()poll()take()poll(timeout,TimeUnit)
获取队首元素element()peek()   -              -

1.抛出异常

public static void test1(){
        //括号里填的是队列大小,看源码
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
        for (int i = 0; i < 3; i++) {
            System.out.println(blockingQueue.add(String.valueOf(i)));
        }
        //获取队首元素
        System.out.println(blockingQueue.element());
        //队列已满,再向队列中添加元素会抛异常  :  Queue full -->  队列已满
        //blockingQueue.add("hhh");
        System.out.println("===================");
        //弹出队列中元素
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        //队列已空,再向队列中取元素会抛出异常 NoSuchElementException --> 没有元素
        //blockingQueue.remove();
    }

 

 2.不抛出异常,有返回值

public static void test2(){
        //同样括号中填队列大小
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
        for (int i = 0; i < 3; i++) {
            System.out.println(blockingQueue.offer(String.valueOf(i)));
        }
        //获取队首元素
        System.out.println(blockingQueue.peek());
        //此时队列已满,再向队列中添加元素会返回false
        System.out.println(blockingQueue.offer("hhh"));
        System.out.println("===========");
        //弹出队列中元素
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        //此时队列为空,再弹出元素不会抛出异常,返回null
        System.out.println(blockingQueue.poll());
    }

 

3.阻塞等待

public static void test3() throws InterruptedException {
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
        for (int i = 0; i < 3; i++) {
            blockingQueue.put(String.valueOf(i));
        }
        //队列没有位置了,会一直阻塞
        //blockingQueue.put("hhhh");
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        //队列为空,会一直阻塞
        //System.out.println(blockingQueue.take());
    }

 

 4.超时等待

public static void test4() throws InterruptedException {
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
        for (int i = 0; i < 3; i++) {
            System.out.println(blockingQueue.offer(String.valueOf(i)));
        }
        //队列已满,设置等待时间,如果等待时间到了元素还没有位置插入,就会超时退出
        //blockingQueue.offer("hhh",2, TimeUnit.SECONDS);
        System.out.println("============");
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        //队列已空,设置等待时间,如果等待时间到了队列中还没有元素,就会超时退出并返回null
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
    }

 

 三、同步队列 SynchronousQueue

和其他BlockingQueue不同

同步队列不存储元素

同队列 put 一个元素 必须等待该元素take出队列后才能put下一个元素

public class SynchronousQueueTest {
    public static void main(String[] args) {
        SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>();
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+" put  1");
                synchronousQueue.put("1");
                System.out.println(Thread.currentThread().getName()+" put  2");
                synchronousQueue.put("2");
                System.out.println(Thread.currentThread().getName()+" put  3");
                synchronousQueue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T1").start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+" get "+synchronousQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+" get "+synchronousQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+" get "+synchronousQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T2").start();
    }
}

 

 

 

 

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐