优先级队列:PriorityQueue: 类似于排队的方式,以某种规则判定优先级先后调用
阻塞队列,是一种特殊的队列,虽然同样是先进先出,但是有特殊的功能。
1. 如果队列为空,执行出队列操作时就会阻塞,直到另一个线程往队列中添加元素为止(队列不空)
2. 如果队列为满,执行入队列操作时就会阻塞,阻塞到另一个线程从队列取走元素为止(队列不满)
阻塞队列经常用于生产者消费者模型:
这里举一个例子,假如我们一家人三口人要吃自己包的饺子,但是只有一个擀面杖,如果三个人分别自己擀面皮然后包饺子的话,会发生擀面杖竞争,影响效率,此时一个人擀面皮另外两个人包,这时就实现了一个类似于“生产者消费者模型”,效率会提升。
但是在程序中生产者消费者模型有一个缺陷,就是耦合很高,在A服务器需要调动B服务器时,两方都需要在各自服务器中拥有对方的调用方法,当一方挂了的时候,另外一个会跟着挂,同时如果此时想再加一个C服务器,则必须改动A中的代码,此时也有可能影响到B服务器。这时候需要我们使用阻塞队列来完成“解耦”
解耦的具体实现:
A服务器作为生产者,将生产出的元素全部抛给一个阻塞队列1,然后其他线程从阻塞队列上提取元素消费后抛给另一个阻塞队列2,A从阻塞队列2中提取元素,这样就完成了一次低耦合的交互。这个操作可以有效地"削峰填谷"。
下面是一个阻塞队列的代码实现:
//阻塞队列 public class ThreadDemo9 { public static void main(String[] args) { MyBlocking queue = new MyBlocking(); //实现一个生产者消费者模式 Thread thread = new Thread(()->{ int num = 0 ; //计数 生产了多少 while (true){ System.out.println("生产了:"+num); try { queue.put(num); num++; } catch (InterruptedException e) { throw new RuntimeException(e); } } }); thread.start(); Thread thread1 = new Thread(()->{ int num = 0; while (true){ try { System.out.println("消费了:"+num); num = queue.take(); Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); thread1.start(); } } class MyBlocking{ //队列 private int []data = new int[1000]; //数组长度 private int size=0; //两个箭头一个指头一个指尾 来判断是否满/空 private int head =0 ; private int tail = 0; private static Object locker = new Object(); //入队列 public void put (int value) throws InterruptedException{ synchronized (locker){ //开始时暂时先返回return/数组满了的时候 size = length 则需要等待notify if (size == data.length){ if(size == 0){ return; } locker.wait(); } //不满时可以向里面加元素 ,并且队列往后走一格 data[tail]= value; tail++; if(tail >= data.length){ tail =0; } size++; locker.notify(); } } //出队列 此时需要包装类(size没有null 包装类有) public Integer take()throws InterruptedException{ synchronized (locker){ if(size ==0 ){ //return null; locker.wait(); } int ret = data[head]; head++; if (head>= data.length){ head = 0; } size --; //take成功之后 唤醒put中的等待 locker.notify(); return ret; } } }