深圳市罗湖网站建设,网站建设哪里实惠,wordpress七牛图片插件,如何用网站模板概念 阻塞队列是带有阻塞功能的队列
特性 当队列满的时候#xff0c;继续入队列#xff0c;就会出现阻塞#xff0c;阻塞到其他线程从队列中取走元素为止 当队列空的时候#xff0c;继续出队列#xff0c;也会发生阻塞#xff0c;阻塞到其他线程往队列中添加元素为止
特…概念 阻塞队列是带有阻塞功能的队列
特性 当队列满的时候继续入队列就会出现阻塞阻塞到其他线程从队列中取走元素为止 当队列空的时候继续出队列也会发生阻塞阻塞到其他线程往队列中添加元素为止
特点 阻塞队列有着解耦合和削峰填谷的主要特点 1.解耦合 两个服务器AB,服务器A负责输送用户请求给服务器B服务器B负责解决用户请求但是两个服务器之间不是直接联系起来的,而是有一个阻塞队列在两个服务器之间服务器A将请求输送给阻塞队列服务器B从阻塞队列中获取请求这样两个服务器之间就不是直接联系耦合性就被降低。 耦合性降低可以避免出现一个服务器发生错误导致另一个服务器也发生错误的情况 2.削峰填谷 同样是两个服务器AB服务器A负责输送用户请求给服务器B有一个阻塞队列在两个服务器之间当出现莫种特殊情况,导致服务器A输送大量的数据到队列中由于阻塞队列满了再添加数据就会发生阻塞等待所以服务器B处理数据的节奏不会被影响,但要是没有阻塞队列服务器A和服务器B是直接连接的话很可能服务器A输送大量的请求给服务器B会导致服务器B崩溃
系统提供的阻塞队列的使用
BlockingQueueInteger queuenew ArrayBlockingQueue(); //底层是顺序表
BlockingQueueInteger queuenew LinkedBlockingQueue(); //底层是链表
BlockingQueueInteger queuenew PriorityBlockingQueue(); //底层是优先级队列堆 调用put方法是添加数据到队列中调用take方法是弹出队列中的数据由于BlockingQueue实现了Queue接口所以它也有offer和poll等方法但只有put和take方法是带阻塞的所以推荐使用put和take方法
代码展示
class MyBlockingQueue{//用循环顺序表来作为阻塞队列的底层实现private String[]itemsnew String[1000];//数据存在的范围是[head,tail)//避免出现内存可见性和指令重排序的问题要对变量加上volatile//指向头部的指针private volatile int head0;//指向尾部的指针private volatile int tail0;//记录阻塞队列中的数据个数private volatile int size0;//put和take方法在多线程中涉及到多个线程改变同一个变量所以要加上锁//向阻塞队列插入数据public void put(String elem) throws InterruptedException {synchronized(this){//判断队列是否满了while (sizeitems.length){ //不一定阻塞等待是被notify正常唤醒的也就不一定队列真的不满了所以要用while循环多次判断//直到真的队列没满才进行接下来的操作wait进行阻塞等待推荐和while一起使用多次判断是否满足唤醒条件this.wait(); //当队列满了就进入阻塞等待}items[tail]elem;tail;size;if(tailitems.length){tail0;}this.notify(); //当向阻塞队列插入数据后便可以唤醒弹出数据的阻塞状态}}//弹出阻塞队列中的数据public String take() throws InterruptedException {synchronized(this){//判断阻塞队列是否为空while (size0){//不一定阻塞等待是被notify正常唤醒的也就不一定队列真的不为空所以要用while循环多次判断//直到真的队列不为空才进行接下来的操作wait进行阻塞等待推荐和while一起使用多次判断是否满足唤醒条件this.wait();}String elemitems[head];head;size--;if(headitems.length){head0;}this.notify(); //弹出一个数据后队列不满了就可以唤醒插入数据的阻塞状态return elem;}}} 代码分析 1.该代码中实现阻塞队列的底层结构是很简单的循环数组 2.由于要满足多线程编程而put和take操作涉及到多个线程修改同一个变量的问题所以需要用synchronized给put和take方法加锁而为了防止出现内存可见性和指令重排序问题对于在多线程中要进行读取修改的变量加上volatile关键字防止编译器进行优化。
关于synchronized和内存可见性和指令重排序可以看线程安全问题线程安全问题内存可见性线程安全问题指令重排序 3.如何实现阻塞呢在put方法中如果队列满了那就要进入阻塞等待就用synchronized加锁的对象调用wait方法进入阻塞等待只有当take方法执行成功才能调用notify唤醒put方法中阻塞等待的线程。 同样在take方法中如果队列空了那就要进入阻塞等待就用synchronized加锁的对象调用wait方法进入阻塞等待只有当put方法执行成功才能调用notify唤醒take方法中阻塞等待的线程。关于wait于notify可以看通过wait和notify来协调线程执行顺序 4.put和take方法要对同一个对象进行加锁因为put和take中要修改的变量有相同的所以当多个线程调用put和take方法时存在线程安全问题所以要对同一个对象进行加锁。 5.判断是否进入阻塞等待的条件是一个while循环推荐wait与while一起使用因为不一定阻塞等待wait是被notify正常唤醒的也就不一定是否真的满足队列不满或者不空的条件所以要进行多次判断要是队列依然还是满或空的话就要再次进入阻塞等待