阻塞队列

队列:先进先出的数据结构(FIFO)

java中的队列接口在java.util包下

常见的对列实现类有LinkedList

 

 

 

常见的阻塞队列:LinkedBlockingDeque,可以设置固定的容量,当队列有数据的时候会通知消费者消费,当对应满的时候会让生产者等待。

用LinkedBlockingDeque实现生产者消费者模式:两个厨师做烧饼,两个顾客买烧饼

  @Test
    public void test15() {
        final int count = 5;
        LinkedBlockingDeque<String> shaobingQueue = new LinkedBlockingDeque<>(3);

//        List<String> xiaoBaiMsg = new LinkedList<>();
        List<String> chushi1Msg = new LinkedList<>();
        List<String> chushi2Msg = new LinkedList<>();
        List<String> roadPeopleAmsg = new LinkedList<>();
        List<String> roadPeopleBmsg = new LinkedList<>();



        Thread roadPeopleA = new Thread(() -> {
            for (int i = 0; i < count; i++) {
                String take = null;
                try {
                    take = shaobingQueue.take();//队列没数据的时候会通知线程等待
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                roadPeopleAmsg.add(String.format("%d 路人甲买到了 [%s]", System.currentTimeMillis(), take));
            }
        });
        Thread roadPeopleB = new Thread(() -> {
            for (int i = 0; i < count; i++) {
                String take = null;
                try {
                    take = shaobingQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                roadPeopleBmsg.add(String.format("%d 路人乙买到了 [%s]", System.currentTimeMillis(), take));
            }
        });

        Thread chushi1 = new Thread(() -> {
            for (int i = 0; i < count; i++) {
                String format = String.format("第%d个烧饼", i + 1);
                try {
                    shaobingQueue.put(format);//当队列满的时候会让线程等待
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                chushi1Msg.add(String.format("%d chushi1制作了 [%s],当前烧饼数量:%d", System.currentTimeMillis(), format, shaobingQueue.size()));
            }
        });
        Thread chushi2 = new Thread(() -> {
            for (int i = 0; i < count; i++) {
                String format = String.format("第%d个烧饼", i + 1);
                try {
                    shaobingQueue.put(format);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                chushi2Msg.add(String.format("%d chushi2制作了 [%s],当前烧饼数量:%d", System.currentTimeMillis(), format, shaobingQueue.size()));
            }
        });

        chushi1.start();
        chushi2.start();
        roadPeopleA.start();
        roadPeopleB.start();

        try {
            chushi1.join();
            chushi2.join();
            roadPeopleA.join();
            roadPeopleB.join();
        } catch (InterruptedException e) {
            SmallTool.printTimeAndThread("join 产生中断 "+ e.getMessage());
        }

        System.out.println(chushi1Msg.stream().collect(Collectors.joining("\n")));
        System.out.println(chushi2Msg.stream().collect(Collectors.joining("\n")));
        System.out.println("--------");
        System.out.println(roadPeopleAmsg.stream().collect(Collectors.joining("\n")));
        System.out.println(roadPeopleBmsg.stream().collect(Collectors.joining("\n")));
    }

 阻塞队列常用的6个方法:

//存放:
put(E) ------ 一直等待
offer(E, long, TimeUnit) ------- 等待一定时间,返回boolean
offer(E) ----------- 不等待,返回boolean

//获取:
take() --------- 一直等待
poll(long, TimeUnit) ------ 等待一定时间,没有返回null
poll() ---------- 不等待,没有返回null

 

常用的阻塞队列:

1、ArrayBlockingQueue:由数组实现的有界队列,需要指定队列的长度,同时我们也可以设置队列是都是公平的,当我们设置了容量后就不能再修改了,符合数组的特性,此队列按照先进先出(FIFO)的原则对元素进行排序,公平指的是消费线程先到的先消费

public ArrayBlockingQueue(int capacity) {...}
public ArrayBlockingQueue(int capacity, boolean fair) {...}

 

2、LinkedBlockingQueue:由链表实现的队列,这个队列的长度是 Integer.MAX_VALUE,可以设置队列长度

 

3、SynchronousQueue:是一个不存储任何元素的阻塞队列,每一个put操作必须等待take操作,否则不能添加元素。同时它也支持公平锁和非公平锁,synchronousQueue 的容量并不是1,而是0。因为它本身不会持有任何元素,它是直接传递的,synchronousQueue 会把元素从生产者直接传递给消费者,在这个过程中能够是不需要存储的

  public SynchronousQueue() {
        this(false);
    }
    public SynchronousQueue(boolean fair) {
        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
    }

 

4、PriorityBlockingQueue:是一个支持优先级排序的无界阻塞队列,可以通过自定义实现 compareTo()方法来指定元素的排序规则,或者通过构造器参数 Comparator来指定排序规则。但是需要注意插入队列的对象必须是可比较大小的,也就是 Comparable的,否则会抛出 ClassCastException异常

 

posted @ 2023-03-23 23:10  曹伟666  阅读(20)  评论(0编辑  收藏  举报