• Java多线程_阻塞队列


    1.什么是阻塞队列
           我们知道,PriorityQueue、LinkedList这些都是非阻塞队列。在我们使用非阻塞队列的时候有一个很大问题,它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,就必须额外地实现同步策略以及线程间唤醒策略,这个实现起来就非常麻烦。但是有了阻塞队列就不一样了,它会对当前线程产生阻塞,比如一个线程从一个空的阻塞队列中取元素,此时线程会被阻塞直到阻塞队列中有了元素。当队列中有元素后,被阻塞的线程会自动被唤醒(不需要我们编写代码去唤醒)。这样提供了极大的方便性。

    2.阻塞队列的种类
             阻塞队列本质上就是队列,它主要有一下几种:

    • ArrayBlockingQueue:基于数组实现的阻塞队列,先进先出队列,有界队列。在创建时必须制定容量大小。并可以指定公平性与非公平性,默认情况下是非公平的,即不保证等待时间最长的队列最优先能够访问队列。
    • LinkedBlockingQueue:基于链表实现的阻塞队列,先进先出队列,有界队列。在创建时如果不指定容量大小,则默认大小为Integer.MAX_VALUE。
    • PriorityBlockingQueue:按照元素的优先级对元素进行排序,按照优先级顺序出队。并且该阻塞队列为无界阻塞队列,即容量没有上限(源码中它没有容器满的信号标志)。
    • DelayQueue:基于PriorityQueue的延时阻塞队列,无界队列。DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。因为DelayQueue是一个无界队列,所以往队列中插入数据的操作永远不会被阻塞,而只有获取数据的操作才会被阻塞。
    • SynchronousQueue:一个不存储元素的阻塞队列。
    • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
    • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

    3.阻塞队列中的几个主要方法

    •        put方法用来向队尾存入元素,如果队列满,则等待;
    •   take方法用来从队首取元素,如果队列为空,则等待;
    •   offer方法用来向队尾存入元素,如果队列满,则等待一定的时间,当时间期限达到时,如果还没有插入成功,则返回false;否则返回true;
    •   poll方法用来从队首取元素,如果队列空,则等待一定的时间,当时间期限达到时,如果取到,则返回null;否则返回取得的元素;

    4.使用(以LinkedBlockingQueue为例)

    import java.util.concurrent.LinkedBlockingQueue;
    
    public class BlockingQueueDemo {
        int size = 10;
        LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(size);
    
        public static void main(String[] args) {
            BlockingQueueDemo bqd = new BlockingQueueDemo();
            Consumer c = bqd.new Consumer();
            Productor p = bqd.new Productor();
            c.setName("消费者");
            p.setName("生产者");
            c.start();
            p.start();
        }
    
        class Consumer extends Thread {
    
            @Override
            public void run() {
                consume();
            }
    
            private void consume() {
                while (true) {
                    try {
                        queue.take();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "消费了一个物品,还有" + queue.size() + "个物品");
                }
            }
        }
    
        class Productor extends Thread {
    
            @Override
            public void run() {
                product();
            }
    
            private void product() {
                while (true) {
                    try {
                        queue.put(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "生产了一个物品,现有" + queue.size() + "个物品");
                }
    
            }
    
        }
    }
  • 相关阅读:
    preg_replace函数/e后门
    php7.0-7.3的bypass disable_function一把梭
    PHP反序列化逃逸
    day2filter_var函数漏洞
    基于 Elasticsearch 聚合搜索实现电商筛选查询功能
    基于SpringBoot + Redis + 轮询实现扫码登录
    教你理解Lambda表达式
    记录解决 Elasticseach 过滤与聚合问题
    基于 MyBatis-Plus 解决数据库逻辑删除与唯一索引问题
    Java8 Stream Lamdba sorted()排序遇到的小坑
  • 原文地址:https://www.cnblogs.com/ericz2j/p/10283533.html
Copyright © 2020-2023  润新知