当前位置: 首页 > news >正文

手机网站编辑网站文章做内链

手机网站编辑,网站文章做内链,搬家公司网站建设价格,烟台网站建设威企汇互联见效付款什么阻塞队列 阻塞队列#xff08;BlockingQueue#xff09;是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。 支持阻塞的插入方法#xff1a;意思是当队列满时#xff0c;队列会阻塞插入元素的线程#xff0c;直到队列不满。支持阻塞的移除方…什么阻塞队列 阻塞队列BlockingQueue是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。 支持阻塞的插入方法意思是当队列满时队列会阻塞插入元素的线程直到队列不满。支持阻塞的移除方法意思是在队列为空时获取元素的线程会等待队列变为非空。 阻塞队列常用于生产者和消费者的场景生产者是向队列里添加元素的线程消费者是从队列里取元素的线程。阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。 四组API 抛出异常当队列满时如果再往队列里插入元素会抛出IllegalStateException“Queue full”异常。当队列空时从队列里获取元素会抛出NoSuchElementException异常。返回特殊值当往队列插入元素时会返回元素是否插入成功成功返回true。如果是移除方法则是从队列里取出一个元素如果没有则返回null。一直阻塞当阻塞队列满时如果生产者线程往队列里put元素队列会一直阻塞生产者线程直到队列可用或者响应中断退出。当队列空时如果消费者线程从队列里take元素队列会阻塞住消费者线程直到队列不为空。超时退出当阻塞队列满时如果生产者线程往队列里插入元素队列会阻塞生产者线程一段时间如果超过了指定的时间生产者线程就会退出。 注意如果是无界阻塞队列队列不可能会出现满的情况所以使用put或offer方法永远不会被阻塞而且使用offer方法时该方法永远返回true。 Java中7种阻塞队列 ArrayBlockingQueue一个由数组结构组成的有界阻塞队列。 LinkedBlockingQueue一个由链表结构组成的有界阻塞队列。 PriorityBlockingQueue一个支持优先级排序的无界阻塞队列。 DelayQueue一个使用优先级队列实现的无界阻塞队列。 SynchronousQueue一个不存储元素的阻塞队列。 LinkedTransferQueue一个由链表结构组成的无界阻塞队列。 LinkedBlockingDeque一个由链表结构组成的双向阻塞队列。 1.ArrayBlockingQueue ArrayBlockingQueue是一个用数组实现的有界阻塞队列。 默认情况下不保证线程公平的访问队列所谓公平访问队列是指阻塞的线程可以按照阻塞的先后顺序访问队列即先阻塞线程先访问队列。非公平性是对先等待的线程是非公平的当队列可用时阻塞的线程都可以争夺访问队列的资格有可能先阻塞的线程最后才访问队列。为了保证公平性通常会降低吞吐量。 下面是公平阻塞队列 ArrayBlockingQueue fairQueue new ArrayBlockingQueue(1000, true);public ArrayBlockingQueue(int capacity, boolean fair) {if (capacity 0)throw new IllegalArgumentException();this.items new Object[capacity];lock new ReentrantLock(fair);notEmpty lock.newCondition();notFull lock.newCondition(); }访问者的公平性是使用可重入锁实现的。 2.LinkedBlockingQueue LinkedBlockingQueue是一个用链表实现的有界阻塞队列。此队列的默认和最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。 3.PriorityBlockingQueue PriorityBlockingQueue是一个支持优先级的无界阻塞队列。默认情况下元素采取自然顺序升序排列。也可以自定义类实现compareTo()方法来指定元素排序规则或者初始化PriorityBlockingQueue时指定构造参数Comparator来对元素进行排序。需要注意的是不能保证同优先级元素的顺序。 4.DelayQueue * DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。 可以将DelayQueue运用在以下应用场景 缓存系统的设计可以用DelayQueue保存缓存元素的有效期使用一个线程循环查询DelayQueue一旦能从DelayQueue中获取元素时表示缓存有效期到了。 定时任务调度使用DelayQueue保存当天将会执行的任务和执行时间一旦从DelayQueue中获取到任务就开始执行比如TimerQueue就是使用DelayQueue实现的。 1如何实现Delayed接口 DelayQueue队列的元素必须实现Delayed接口。 public interface Delayed extends ComparableDelayed {long getDelay(TimeUnit unit); }参考ScheduledThreadPoolExecutor里ScheduledFutureTask类的实现一共有三步。 第一步在对象创建的时候初始化基本数据。使用time记录当前对象延迟到什么时候可以使用使用sequenceNumber来标识元素在队列中的先后顺序。 private static final AtomicLong sequencer new AtomicLong();ScheduledFutureTask(Runnable r, V result, long ns, long period) {super(r, result);this.time ns;this.period period;this.sequenceNumber sequencer.getAndIncrement();}第二步实现getDelay方法该方法返回当前元素还需要延时多长时间单位是纳秒 public long getDelay(TimeUnit unit) {return unit.convert(time - now(), NANOSECONDS);}延迟时间参数的单位是纳秒自己设计的时候最好使用纳秒实现getDelay()方法时可以指定任意单位一旦以秒或分作为单位而延时时间又精确不到纳秒会出现误差。 第三步实现compareTo方法来指定元素的顺序。 下述代码让延时时间最长的放在队列的末尾 public int compareTo(Delayed other) {if (other this) // compare zero if same objectreturn 0;if (other instanceof ScheduledFutureTask) {ScheduledFutureTask? x (ScheduledFutureTask?)other;long diff time - x.time;if (diff 0)return -1;else if (diff 0)return 1;else if (sequenceNumber x.sequenceNumber)return -1;elsereturn 1;}long diff getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);return (diff 0) ? -1 : (diff 0) ? 1 : 0;}2如何实现延时阻塞队列 当消费者从队列里获取元素时如果元素没有达到延时时间就阻塞当前线程。 take方法 long delay first.getDelay(TimeUnit.NANOSECONDS); if (delay 0)return q.poll(); else if (leader ! null)available.await(); else {Thread thisThread Thread.currentThread();leader thisThread;try {available.awaitNanos(delay);} finally {if (leader thisThread)leader null;}}变量leader是一个等待获取队列头部元素的线程。 如果leader不等于空表示已经有线程在等待获取队列的头元素。使用await()方法让当前线程等待信号。 如果leader等于空则把当前线程设置成leader并使用awaitNanos()方法让当前线程等待接收信号或等待delay时间。 5.SynchronousQueue SynchronousQueue是一个不存储元素的阻塞队列。每一个put操作必须等待一个take操作否则不能继续添加元素。 它支持公平访问队列。默认情况下线程采用非公平性策略访问队列。构造设置为true则等待的线程会采用先进先出的顺序访问队列。 队列本身并不存储任何元素非常适合传递性场景负责把生产者线程处理的数据直接传递给消费者线程。SynchronousQueue的吞吐量高于LinkedBlockingQueue和ArrayBlockingQueue。 6.LinkedTransferQueue LinkedTransferQueue是一个由链表结构组成的无界阻塞TransferQueue队列。相对于其他阻塞队列LinkedTransferQueue多了tryTransfer和transfer方法。 1transfer方法 如果当前有消费者正在等待接收元素消费者使用take()方法或带时间限制的poll()方法时transfer方法可以把生产者传入的元素立刻transfer传输给消费者。 如果没有消费者在等待接收元素transfer方法会将元素存放在队列的tail节点并等到该元素被消费者消费了才返回。 transfer方法的关键代码 // ... Node pred tryAppend(s, haveData); return awaitMatch(s, pred, e, (how TIMED), nanos);第一行试图把存放当前元素的s节点作为tail节点。 第二行让CPU自旋等待消费者消费元素。因为自旋会消耗CPU所以自旋一定的次数后使用Thread.yield()方法来暂停当前正在执行的线程并执行其他线程。 2tryTransfer方法 tryTransfer方法是用来试探生产者传入的元素是否能直接传给消费者。 如果没有消费者等待接收元素则返回false。和transfer方法的区别是tryTransfer方法无论消费者是否接收方法立即返回而transfer方法是必须等到消费者消费了才返回。 带有时间限制的tryTransferE elong timeoutTimeUnit unit方法试图把生产者传入的元素直接传给消费者但是如果没有消费者消费该元素则等待指定的时间再返回如果超时还没消费元素则返回false如果在超时时间内消费了元素则返回true。 7.LinkedBlockingDeque LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列。所谓双向队列指的是可以从队列的两端插入和移出元素。 双向队列多了一个操作队列的入口在多线程同时入队时也就减少了一半的竞争。 LinkedBlockingDeque多了addFirst、addLast、offerFirst、offerLast、peekFirst和peekLast等方法以First单词结尾的方法表示插入、获取peek或移除双端队列的第一个元素。以Last单词结尾的方法表示插入、获取或移除双端队列的最后一个元素。另外插入方法add等同于addLast移除方法remove等效于removeFirst。 在初始化LinkedBlockingDeque时可以设置容量防止其过度膨胀。另外双向阻塞队列可以运用在“工作窃取”模式中。 阻塞队列的实现原理 如果队列是空的消费者会一直等待当生产者添加元素时消费者是如何知道当前队列有元素的呢 使用通知模式实现。所谓通知模式就是当生产者往满的队列里添加元素时会阻塞住生产者当消费者消费了一个队列中的元素后会通知生产者当前队列可用。 以ArrayBlockingQueue为例ArrayBlockingQueue使用了Condition来实现await、signal方法 // 队列两种状态空或者满 两个Condition对象 等待通知 private final Condition notFull; private final Condition notEmpty; public ArrayBlockingQueue(int capacity, boolean fair) {// ... notEmpty lock.newCondition();notFull lock.newCondition();} public void put(E e) throws InterruptedException {checkNotNull(e);final ReentrantLock lock this.lock;lock.lockInterruptibly();try {while (count items.length)notFull.await();enqueue(e);} finally {lock.unlock();} } public E take() throws InterruptedException {final ReentrantLock lock this.lock;lock.lockInterruptibly();try {while (count 0)notEmpty.await();return dequeue();} finally {lock.unlock();} } private void enqueue(E x) {final Object[] items this.items;items[putIndex] x;if (putIndex items.length)putIndex 0;count;notEmpty.signal(); }调用Condition#await方法会将同步队列中的头节点获取锁的线程释放锁转移到等待队列中。 当往队列里插入一个元素时如果队列不可用那么阻塞生产者主要通过LockSupport.parkthis来实现。 public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();Node node addConditionWaiter();int savedState fullyRelease(node);int interruptMode 0;// 此时当前节点已经不在同步队列中while死循环while (!isOnSyncQueue(node)) {// 阻塞当前线程LockSupport.park(this);if ((interruptMode checkInterruptWhileWaiting(node)) ! 0)break;}if (acquireQueued(node, savedState) interruptMode ! THROW_IE)interruptMode REINTERRUPT;if (node.nextWaiter ! null) // clean up if cancelledunlinkCancelledWaiters();if (interruptMode ! 0)reportInterruptAfterWait(interruptMode);}继续进入源码发现调用setBlocker先保存一下将要阻塞的线程然后调用unsafe.park阻塞当前线程。 public static void park(Object blocker) {Thread t Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, 0L);setBlocker(t, null);}unsafe.park是个native方法 public native void park(boolean isAbsolute, long time);park这个方法会阻塞当前线程只有以下4种情况中的一种发生时该方法才会返回。 与park对应的unpark执行或已经执行时。“已经执行”是指unpark先执行然后再执行park的情况。线程被中断时。等待完time参数指定的毫秒数时。异常现象发生时这个异常现象没有任何原因。 JVM是如何实现park方法park在不同的操作系统中使用不同的方式实现在Linux下使用的是系统方法pthread_cond_wait实现。实现代码在JVM源码路径src/os/linux/vm/os_linux.cpp里的os::PlatformEvent::park方法 void os::PlatformEvent::park() {int v ;for (;;) {v _Event ;if (Atomic::cmpxchg (v-1, _Event, v) v) break ;}guarantee (v 0, invariant) ;if (v 0) {// Do this the hard way by blocking ...int status pthread_mutex_lock(_mutex);assert_status(status 0, status, mutex_lock);guarantee (_nParked 0, invariant) ; _nParked ;while (_Event 0) {// !!! status pthread_cond_wait(_cond, _mutex);// for some reason, under 2.7 lwp_cond_wait() may return ETIME ...// Treat this the same as if the wait was interruptedif (status ETIME) { status EINTR; }assert_status(status 0 || status EINTR, status, cond_wait);}-- _nParked ;// In theory we could move the ST of 0 into _Event past the unlock(),// but then wed need a MEMBAR after the ST._Event 0 ;status pthread_mutex_unlock(_mutex);assert_status(status 0, status, mutex_unlock);}guarantee (_Event 0, invariant) ;}}pthread_cond_wait是一个多线程的条件变量函数cond是condition的缩写字面意思可以理解为线程在等待一个条件发生这个条件是一个全局变量。方法接收两个参数一个共享变量 _cond一个互斥量 _mutex。而unpark方法在Linux下是使用pthread_cond_signal实现的。park方法在Windows下则是使用WaitForSingleObject实现的。
http://www.huolong8.cn/news/20645/

相关文章:

  • 网站模板怎么设计网站备案完电信
  • 湖北皇奥建设工程有限公司网站泰安网络犯罪案件
  • 仙桃网站设计公司辽宁建设工程招标信息网官网
  • 2021年新闻大事件什么样的网站好优化
  • 亚马逊网站建设评述杭州公司注销流程及费用
  • 正规建网站企业建设厅网站举报
  • 死链对网站的影响巨量算数数据分析
  • 广告 网站举例创新的模板网站建设
  • 婚庆公司网站模板下载建设专业网站
  • 贸易公司做网站有优势吗大数据开发过程
  • 建立网站需要做什么微信开发小程序工具
  • 做国外百科知识网站做网站赚钱 知乎
  • 深圳网站建设 东莞网站建设网络工程师题库
  • 建网站流程seo网站推广专员
  • 系部 网站建设方案如何建一个外贸网站
  • 低价格制作网站沈阳seo关键词排名
  • 域名备案要先做网站的吗合肥建站网站
  • 建网站需要多少钱和什么条件赣州酒店网站设计
  • 做学校和企业对接的网站无法访问网站
  • 如何在招聘网站上选个好公司做销售上海建设安全生产协会网站
  • 嘉祥县建设局网站百度云盘做网站
  • 房地产景区网站建设方案优秀购物网站建设
  • 做网站英文编辑有前途网络设计方案书主要包括哪些内容
  • wordpress用外部图片浙江企业seo推广
  • c2c网站有哪些网站建设与开发学什么内容呢
  • 佛山网站建设网络推广做关于植物的网站
  • 网站对于企业的作用公司网站建设多少费用哪儿济南兴田德润联系电话
  • 吉林新农村建设网站附近装修公司联系方式
  • 网站建设学习网公司有哪些住房和城乡建设部网站证书查询
  • 上海网站营销网络设计课程培训