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

网站提示框代码下载2345浏览器并安装

网站提示框代码,下载2345浏览器并安装,品牌服务推广,洛阳青峰网络公司做网站1. Condition的signal方法分析 分为了几个部分#xff1a; ● 确保执行signal方法的是持有锁的线程 ● 脱离Condition的队列 ● 将Node状态从-2改为0 ● 将Node添加到AQS队列 ● 为了避免当前Node无法在AQS队列正常唤醒做了一些判断和操作 // 线程挂起后#xff0c;可以基于…1. Condition的signal方法分析 分为了几个部分 ● 确保执行signal方法的是持有锁的线程 ● 脱离Condition的队列 ● 将Node状态从-2改为0 ● 将Node添加到AQS队列 ● 为了避免当前Node无法在AQS队列正常唤醒做了一些判断和操作 // 线程挂起后可以基于signal唤醒~ public final void signal() {// 在ReentrantLock中如果执行signal的线程没有持有锁资源直接扔异常 if (!isHeldExclusively()) throw new IllegalMonitorStateException(); // 拿到排在Condition首位的Node Node first firstWaiter; // 有Node在排队才需要唤醒如果没有直接告辞~~ if (first ! null) doSignal(first); } // 开始唤醒Condition中的Node中的线程 private void doSignal(Node first) { // 先一波do-while走你~~~ do { // 获取到第二个节点并且将第二个节点设置为firstWaiter if ( (firstWaiter first.nextWaiter) null) // 说明就一个节点在Condition队列中那么直接将firstWaiter和lastWaiter置位null lastWaiter null; // 如果还有nextWaiter节点因为当前节点要被唤醒了脱离整个Condition队列。将nextWaiter置位null first.nextWaiter null; // 如果transferForSignal返回true一切正常退出while循环 } while (!transferForSignal(first) // 如果后续节点还有往后面继续唤醒如果没有退出while循环 (first firstWaiter) ! null); } // 准备开始唤醒在Condition中排队的Node final boolean transferForSignal(Node node) { // 将在Condition队列中的Node的状态从-2改为0代表要扔到AQS队列了。 if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) // 如果失败了说明在signal之前应当是线程被中断了从而被唤醒了。 return false; // 如果正常的将Node的状态从-2改为0这是就要将Condition中的这个Node扔到AQS的队列。 // 将当前Node扔到AQS队列返回的p是当前Node的prev Node p enq(node); // 获取上一个Node的状态 int ws p.waitStatus; // 如果ws 0 说明这个Node已经被取消了。 // 如果ws状态不是取消将prev节点的状态改为-1,。 if (ws 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) // 如果prev节点已经取消了可能会导致当前节点永远无法被唤醒。立即唤醒当前节点基于acquireQueued方法 // 让当前节点找到一个正常的prev节点并挂起线程 // 如果prev节点正常但是CAS修改prev节点失败了。证明prev节点因为并发原因导致状态改变。还是为了避免当前 // 节点无法被正常唤醒提前唤醒当前线程基于acquireQueued方法让当前节点找到一个正常的prev节点并挂起线程 LockSupport.unpark(node.thread); // 返回true return true; } 2. Conditiond的await方法分析后置分析 分为了几个部分 ● 唤醒之后要先确认是中断唤醒还是signal唤醒还是signal唤醒后被中断 ● 确保当前线程的Node已经在AQS队列中 ● 执行acquireQueued方法等待锁资源。 ● 在获取锁资源后要确认是否在获取锁资源的阶段被中断过如果被中断过并且不是THROW_IE那就确保 interruptMode是REINTERRUPT。 ● 确认当前Node已经不在Condition队列中了 ● 最终根据interruptMode来决定具体做的事情 ● 0嘛也不做。 ● THROW_IE抛出异常 ● REINTERRUPT执行线程的interrupt方法 // 现在分析await方法的后半部分 public final void await() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Node node addConditionWaiter(); int savedState fullyRelease(node); // 中断模式~ int interruptMode 0; while (!isOnSyncQueue(node)) { LockSupport.park(this); // 如果线程执行到这说明现在被唤醒了。 // 线程可以被signal唤醒。如果是signal唤醒可以确认线程已经在AQS队列中 // 线程可以被interrupt唤醒线程被唤醒后没有在AQS队列中。 // 如果线程先被signal唤醒然后线程中断了。。。。做一些额外处理 // checkInterruptWhileWaiting可以确认当前中如何唤醒的。 // 返回的值有三种 // 0正常signal唤醒没别的事不知道Node是否在AQS队列// THROW_IE-1中断唤醒并且可以确保在AQS队列 // REINTERRUPT1signal唤醒但是线程被中断了并且可以确保在AQS队列 if ((interruptMode checkInterruptWhileWaiting(node)) ! 0) break; } // Node一定在AQS队列 // 执行acquireQueued尝试在ReentrantLock中获取锁资源。 // acquireQueued方法返回true代表线程在AQS队列中挂起时被中断过 if (acquireQueued(node, savedState) interruptMode ! THROW_IE) // 如果线程在AQS队列排队时被中断了并且不是THROW_IE状态确保线程的interruptMode是REINTERRUPT // REINTERRUPTawait不是中断唤醒但是后续被中断过 interruptMode REINTERRUPT; // 如果当前Node还在condition的单向链表中脱离Condition的单向链表 if (node.nextWaiter ! null) unlinkCancelledWaiters(); // 如果interruptMode是0说明线程在signal后以及持有锁的过程中没被中断过什么事都不做 if (interruptMode ! 0) // 如果不是0~ reportInterruptAfterWait(interruptMode); } // 判断当前线程被唤醒的模式确认interruptMode的值。 private int checkInterruptWhileWaiting(Node node) { // 判断线程是否中断了。 return Thread.interrupted() ? // THROW_IE代表线程是被interrupt唤醒的需要向上排除异常 // REINTERRUPT代表线程是signal唤醒的但是在唤醒之后被中断了。(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : // 线程是正常的被signal唤醒并且线程没有中断过。 0; } // 判断线程到底是中断唤醒的还是signal唤醒的 final boolean transferAfterCancelledWait(Node node) { // 基于CAS将Node的状态从-2改为0 if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) { // 说明是中断唤醒的线程。因为CAS成功了。 // 将Node添加到AQS队列中~如果是中断唤醒的当前线程同时存在Condition的单向链表以及AQS的队列中 enq(node); // 返回true return true; } // 判断当前的Node是否在AQS队列signal唤醒的但是可能线程还没放到AQS队列 // 等到signal方法将线程的Node扔到AQS队列后再做后续操作 while (!isOnSyncQueue(node)) // 如果没在AQS队列上那就线程让步稍等一会Node放到AQS队列再处理看CPU Thread.yield(); // signal唤醒的返回false return false; } // 确认Node是否在AQS队列上 final boolean isOnSyncQueue(Node node) { // 如果线程状态为-2肯定没在AQS队列// 如果prev节点的值为null肯定没在AQS队列 if (node.waitStatus Node.CONDITION || node.prev null) // 返回false return false; // 如果节点的next不为null。说明已经在AQS队列上。、 if (node.next ! null) // 确定AQS队列上有 return true; // 如果上述判断都没有确认节点在AQS队列上在AQS队列中寻找一波 return findNodeFromTail(node); } // 在AQS队列中找当前节点 private boolean findNodeFromTail(Node node) { // 拿到尾节点 Node t tail; for (;;) { // tail是否是当前节点如果是说明在AQS队列 if (t node) // 可以跳出while循环 return true; // 如果节点为nullAQS队列中没有当前节点 if (t null) // 进入while让步一手 return false; // t向前引用 t t.prev; } } private void reportInterruptAfterWait(int interruptMode) throws InterruptedException { // 如果是中断唤醒的await直接抛出异常 if (interruptMode THROW_IE) throw new InterruptedException(); // 如果是REINTERRUPTsignal后被中断过 else if (interruptMode REINTERRUPT) // 确认线程的中断标记位是true // Thread.currentThread().interrupt(); selfInterrupt(); } 3 Condition的awaitNanossignalAll方法分析 awaitNanos仅仅是在await方法的基础上做了一内内的改变整体的逻辑思想都是一样的。 挂起线程时传入要阻塞的时间时间到了自动唤醒走添加到AQS队列的逻辑 // await指定时间多了个时间到了自动醒。 public final long awaitNanos(long nanosTimeout) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Node node addConditionWaiter(); int savedState fullyRelease(node); // deadline当前线程最多挂起到什么时间点final long deadline System.nanoTime() nanosTimeout; int interruptMode 0; while (!isOnSyncQueue(node)) { // nanosTimeout的时间小于等于0直接告辞 if (nanosTimeout 0L) { // 正常扔到AQS队列 transferAfterCancelledWait(node); break; } // nanosTimeout的时间大于1000纳秒时才可以挂起线程 if (nanosTimeout spinForTimeoutThreshold) // 如果大于正常挂起 LockSupport.parkNanos(this, nanosTimeout); if ((interruptMode checkInterruptWhileWaiting(node)) ! 0) break; // 计算剩余的挂起时间可能需要重新的走while循环再次挂起线程 nanosTimeout deadline - System.nanoTime(); } if (acquireQueued(node, savedState) interruptMode ! THROW_IE) interruptMode REINTERRUPT; if (node.nextWaiter ! null) unlinkCancelledWaiters(); if (interruptMode ! 0) reportInterruptAfterWait(interruptMode); // 剩余的挂起时间 return deadline - System.nanoTime(); } signalAll方法。这个方法一看就懂之前signal是唤醒1个这个是全部唤醒 // 以do-while的形式将Condition单向链表中的所有Node全部唤醒并扔到AQS队列 private void doSignalAll(Node first) { // 将头尾都置位null~ lastWaiter firstWaiter null; do { // 拿到next节点的引用 Node next first.nextWaiter; // 断开当前Node的nextWaiter first.nextWaiter null; // 修改Node状态扔AQS队列是否唤醒 transferForSignal(first); // 指向下一个节点 first next; } while (first ! null); }
http://www.huolong8.cn/news/135841/

相关文章:

  • 微网站运营私人承包小工程哪里有
  • wordpress如何启用全站sslwordpress新建404页面
  • 网站运营阶段怎么做自己淘宝优惠券网站
  • 网站手机app开发东乡族网站建设
  • 郑州快速网站优化公司哪家好开发菏泽网站建设
  • 如何选择低价网站建设win7配置不能运行wordpress
  • 邹平网站定制网站的构建一般要多久
  • 域名注册网站建设初级网站开发的自我推荐
  • 现在网站建设用什么语言安徽水利建设市场信用信息平台网站
  • 马蜂窝网站怎么做wordpress 微信 支付宝
  • 网站建设流程有哪些中国建设银行下载官方网站
  • 闸北网站建设公司十堰seo优化服务
  • 有没有网站做字体变形微信公众号运营策划书范文
  • 搬家公司网站建设价格嘉兴信息发布终端多少钱一台
  • internet网站建设试卷营销app
  • 网站建设项目描述范文网站建设有哪些公司
  • 建设招标网网站网站建设教程免费湖南岚鸿
  • 做网站导航站的注意点微软做网页的软件
  • 网站论坛推广文案怎么做建网站中企动力优
  • 做网站一般怎么收费的深圳网站建设软件开发
  • 长春市长春网站制作站优化新增备案网站要关闭吗
  • 电子商务网站营销的方法大连搜狗
  • 网站建设哪里好网站主办单位负责人
  • 代网站备案费用国家公信网查询系统
  • 单页网站seo优化wordpress photoshop
  • 网站产品怎么改顺序营销网站报备
  • 个人网站的订单怎么建设一个优秀的网站
  • 网站建设运行工作情况总结装修平台网站排名前十名有哪些
  • 郑州专业网站推广公司丰县住房与城乡建设部网站
  • 企业网站建设软件网站开发 需要用到什么软件有哪些