Java面试题(十三) 阻塞队列之神兵出鞘

一. 阻塞队列

1. 常见的阻塞队列:

	ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,
	此队列按FIFO原则对元素进行排序。
	
	LinkedBlockingQueue:是一个基于链表结构的阻塞队列,
	此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。
	
	SynchronousQueue:是一个不存储元素的阻塞队列,
	每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,
	吞吐量通常要高于LinkedBlockingQueue。

2. ArrayBlockingQueue基础操作(API)

private static void Demo01() {
        //阻塞队列,需要设置初始值
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        //添加
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        /**
         * 超出队列容量,在添加会报错。
         *  java.lang.IllegalStateException: Queue full
         */
        //System.out.println(blockingQueue.add("x"));

        //输出队头元素,可以判断这个队列是否为空。
        System.out.println(blockingQueue.element());

        //移出
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        /**
         * 队列没有内容,在移出会报错。
         *  java.util.NoSuchElementException
         */
        //System.out.println(blockingQueue.remove());
    }
 private static void Demo02() {
        //阻塞队列,需要设置初始值
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        //添加
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        //添加不进去,不报错返回 false
        System.out.println(blockingQueue.offer("x"));

        //检查队头元素
        System.out.println(blockingQueue.peek());

        //移出
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        //队列为空,输出时也不报错,输出 null。
        System.out.println(blockingQueue.poll());
    }
private static void Demo03() throws InterruptedException {
        //阻塞队列,需要设置初始值
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        //添加
        blockingQueue.put("a");
        blockingQueue.put("b");
        blockingQueue.put("c");
        //添加不进去,不报错,不返回,一直阻塞着,直到有地方为止。
        //blockingQueue.put("x");

        //取值
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        //队列为空,输出时也不报错,也不输出null,在那阻塞着。
        System.out.println(blockingQueue.take());
    }
public static void main(String[] args) throws Exception {

        //阻塞队列,需要设置初始值
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("b", 2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("c", 2L, TimeUnit.SECONDS));
        //阻塞 2秒后,输出 false
        System.out.println(blockingQueue.offer("x", 2L, TimeUnit.SECONDS));

    }

3. SynchronousQueue基础操作(API)

public static void main(String[] args) {
        //不存储阻塞队列
        BlockingQueue<String> blockingQueue = new SynchronousQueue<>();

        //该线程负责加入数据
        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "\t put 1");
                blockingQueue.put("1");
                System.out.println(Thread.currentThread().getName() + "\t put 2");
                blockingQueue.put("2");
                System.out.println(Thread.currentThread().getName() + "\t put 3");
                blockingQueue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "T1").start();

        //该线程负责移出数据
        new Thread(() -> {
            try {
                //休眠 3秒,看一下效果。
                try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(Thread.currentThread().getName() + "   " + blockingQueue.take());
                try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(Thread.currentThread().getName() + "   " + blockingQueue.take());
                try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(Thread.currentThread().getName() + "   " + blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "T2").start();

    }

运行结果:
在这里插入图片描述

总结:熟悉阻塞队列基本API,为后面实现阻塞队列版生产者消费者模式打下坚实的基础。

猜你喜欢

转载自blog.csdn.net/w_x_A__l__l/article/details/106903025