手机网站轮播图,企业网站设计方案书,网站设计心得体会,网页游戏平台在线玩一.什么是阻塞队列#xff1f; 1.如果对于一个满的队列#xff0c;还要把元素入队列#xff0c;此时这个队列就会阻塞等待#xff0c;一直阻塞到这个队列不满为止#xff0c;从而把这个元素入队列#xff01; 2.如果对于一个空的队列#xff0c;还要从队列拿出元素… 一.什么是阻塞队列 1.如果对于一个满的队列还要把元素入队列此时这个队列就会阻塞等待一直阻塞到这个队列不满为止从而把这个元素入队列 2.如果对于一个空的队列还要从队列拿出元素此时这个队列就会阻塞等待一直阻塞到这个队列不空为止从而把这个元素拿出队列 二.阻塞队列有什么作用
1.解耦合作用 什么是耦合度 耦合度高就是模块之间联系比较紧密彼此之间互相影响 耦合度低就是模块之间联系没有那么紧密也就是模块之间影响小。 此时引入阻塞队列就可以有效降低模块之间的耦合度起到了解耦合的作用 看图 2.削峰填谷作用 三.代码的实现
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class ThreadDemo11 {public static void main(String[] args) throws InterruptedException {BlockingQueueString queue new ArrayBlockingQueue(100);queue.put(666);String squeue.take();System.out.println(s);squeue.take();System.out.println(s);}
}
此时阻塞等待 四.自己模拟实现
//实现阻塞队列
class MyBlockingQueue{//这个是模拟实现队列private String[] elems null;private int head 0;private int tail 0;private int size 0;private Object locker new Object();//实现构造方法public MyBlockingQueue(int capacity){elems new String[capacity];}//放进元素public void put (String elem) throws InterruptedException {synchronized (locker){//超出队列长度//使用while循环是防止线程唤醒后只判断一次让被唤醒的线程再判断一次while(size elems.length){locker.wait();}//往这里加元素elems[tail] elem;tail;//这里面是循环队列可使这块空间能够被循环利用所以需要tail 0if(tail elems.length){tail 0;}size;locker.notify();}}//拿出元素public String take() throws InterruptedException {String elem null;//队列里面没有元素阻塞等待synchronized (locker){while(size 0){locker.wait();}//拿出一个元素elem elems[head];head;if(head elems.length){head 0;}size--;locker.notify();}return elem;}}public class ThreadDemo10 {public static void main(String[] args) {MyBlockingQueue myBlockingQueue new MyBlockingQueue(1000);//创建两个线程实现生产者和消费者模型Thread t1 new Thread(()-{int n 1;while(true){try {myBlockingQueue.put(n);System.out.println(生产元素n);n;} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread t2 new Thread(()-{while(true){try {String n myBlockingQueue.take();System.out.println(消费元素n);Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}}});//线程的启动t1.start();t2.start();}
}代码中的一些问题 是否能够把里面这个while改成if if(size elems.length){locker.wait();}
答案是不能的为什么呢 假设这个队列的容量是1且此时容量已满。假设有3个线程t1t2、t3. t1和t2都调用put此时t1线程进入wait状态由于wait状态t1线程释放了锁。然后 t2也进入了锁里面进入wait状态也释放了锁。 t3线程执行take从线程中拿出了一个元素然后进行notify随机唤醒了其中一个线程假设唤醒了t1线程t1线程把一个元素放进了队列此时队列满了然后notify唤醒了t2 线程由于if操作已经执行过了所以它要把元素放进队列由于队列容量为1所以t2无法把元素放进队列中此时代码便出现了问题。 由此可见使用while可以使线程唤醒之后再判断一次条件进而避免了线程安全的问题 五.生产者-消费者模型
这就可以使用阻塞队列来完成 此时这个生产元素的速度要比消费元素速度要快所以队列会先满了然后阻塞等待最后就是消费一个元素生产一个元素趋于平衡。 那么就会有人说队列的容量不是1000为什么会出现1001
原因就在于线程的调度是不确定的。 当生产元素1000已经达到了队列的容量这是毋庸置疑的。然后线程进行消费元素然后notify唤醒了生产元素的线程此时这个消费元素还没有打印然后这个生产元素的线程打印了生产元素1001。