《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:延迟队列,线程安全,阻塞,无界,到了时间之后才能取走。