《Java基础知识》Java 阻塞队列

前言

学习RabbitMQ的时候了解到了阻塞队列(ArrayBlockingQueue,LinkedBlockingDeque,SynchronousQueue),那就一起来了解一下这些阻塞队列。

说明

阻塞队列提供了四种处理方法:

通过案例实现一个ArrayBlockingQueue的使用案例

public class QueueTest {
    static ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(100000);


    public static void main(String[] args) {
        Runnable runnable0 = () -> {
            int i = 0;
            while(true){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("add:"+i);
                arrayBlockingQueue.add(i++);
            }
        };

        Runnable runnable1 = () -> {
            int i = 0;
            while(true){
                try {
                    Thread.sleep(200);
                    System.out.println("remove:"+arrayBlockingQueue.remove());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        Thread thread0 = new Thread(runnable0);
        Thread thread1 = new Thread(runnable1);
        thread0.start();
        thread1.start();
    }
}

运行结果:

队列使用基本都一致,不同的队列也是有一些区别的。

SynchronousQueue:无缓冲队列,放入一个元素必须等其他线程获取之后才能再放入,用于阻塞线程的。

通过案例看看SynchronousQueue如何使用

public class SynQueueTest {

    static SynchronousQueue synchronousQueue = new SynchronousQueue();


    public static void main(String[] args) {
        Runnable runnable0 = () -> {
            while(true){
                try {
                    Thread.sleep(100);
                    System.out.println("add");
                    synchronousQueue.put("add");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };

        Runnable runnable1 = () -> {
            int i = 0;
            while(true){
                try {
                    Thread.sleep(200);
                    System.out.println("take"+synchronousQueue.take());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        Thread thread0 = new Thread(runnable0);
        Thread thread1 = new Thread(runnable1);
        thread0.start();
        thread1.start();
    }
}

运行结果:

SynchronousQueue使用用来阻塞线程的,保证一对一匹配之后put 和 take 都释放。

总结

ArrayBlockingQueue:是一个用数组实现的有界阻塞队列,此队列按照先进先出(FIFO)的原则对元素进行排序。支持公平锁和非公平锁。【注:每一个线程在获取锁的时候可能都会排队等待,如果在等待时间上,先获取锁的线程的请求一定先被满足,那么这个锁就是公平的。反之,这个锁就是不公平的。公平的获取锁,也就是当前等待时间最长的线程先获取锁】

LinkedBlockingQueue:一个由链表结构组成的有界队列,此队列的默认长度为Integer.MAX_VALUE。此队列按照先进先出的顺序进行排序,因为入队和出队不是同一锁,入队和出队不阻塞。

PriorityBlockingQueue: 一个支持线程优先级排序的无界队列,默认自然序进行排序,也可以自定义实现compareTo()方法来指定元素排序规则,不能保证同优先级元素的顺序。

SynchronousQueue:无缓冲队列,放入一个元素必须等其他线程获取之后才能再放入,用于阻塞线程的。

ConcurrentLinkedQueue:非阻塞队列,通过自旋实现线程安全,不能被线程池中,性能消耗多。

PriorityQueue:非线程安全,优先级队列,无界。

DelayQueue:延迟队列,线程安全,阻塞,无界,到了时间之后才能取走。

原文地址:https://www.cnblogs.com/jssj/p/13783053.html