丙烯酸价格,公牛队标志,石芒铁分布
object类中的wait(),notify()和notifyall()可以实现线程的等待通知模型,同样在reentrantlock中可以借助condition来完成这种机制。本篇就简要介绍condition的工作原理。
先看一下condition的使用示例:
public class lockconditiontest { private reentrantlock lock = new reentrantlock(); private condition condition = lock.newcondition(); /** * 等待方法 */ private void startawait() { try { lock.lock(); system.out.println("开始等待:" + system.currenttimemillis()); condition.await(); system.out.println("等待结束:" + system.currenttimemillis()); } catch (interruptedexception e) { e.printstacktrace(); }finally{ lock.unlock(); } } /** * 释放方法 */ private void startsignal() { try { lock.lock(); system.out.println("开始释放"); condition.signal(); } catch (exception e) { e.printstacktrace(); }finally { //这里锁被主线程持有,必须释放,让被唤醒的mythread能够得到锁 lock.unlock(); } } public static void main(string[] args) throws interruptedexception { lockconditiontest test = new lockconditiontest(); mythread mythread = new lockconditiontest().new mythread(test); //开始线程。 让线程等待。 mythread.start(); //mythread调用condition.await()释放锁,main线程开始执行 timeunit.milliseconds.sleep(1000); //主线程唤醒等待线程 test.startsignal(); } class mythread extends thread{ private lockconditiontest test; public mythread(lockconditiontest test) { this.test = test; } @override public void run() { //开始等待,释放锁 test.startawait(); } } }
这段代码的输出为:
开始等待:1550285191899
开始释放
等待结束:1550285192902
等待时间大概为1000毫秒,符合预期。
下面看看condition的await()方法:
public final void await() throws interruptedexception { if (thread.interrupted()) throw new interruptedexception(); node node = addconditionwaiter(); // 1 int savedstate = fullyrelease(node); // 2 int interruptmode = 0; while (!isonsyncqueue(node)) { locksupport.park(this); // 3 if ((interruptmode = checkinterruptwhilewaiting(node)) != 0) break; } if (acquirequeued(node, savedstate) && interruptmode != throw_ie) interruptmode = reinterrupt; if (node.nextwaiter != null) // clean up if cancelled unlinkcancelledwaiters(); if (interruptmode != 0) reportinterruptafterwait(interruptmode); }
主要分为3步:
再看看signal()方法:
public final void signal() { if (!isheldexclusively()) throw new illegalmonitorstateexception(); node first = firstwaiter; // 1 if (first != null) dosignal(first); } private void dosignal(node first) { do { if ( (firstwaiter = first.nextwaiter) == null) lastwaiter = null; first.nextwaiter = null; } while (!transferforsignal(first) && (first = firstwaiter) != null); } final boolean transferforsignal(node node) { if (!compareandsetwaitstatus(node, node.condition, 0)) // 2 return false; node p = enq(node); int ws = p.waitstatus; if (ws > 0 || !compareandsetwaitstatus(p, ws, node.signal)) locksupport.unpark(node.thread); // 3 return true; }
如果要唤醒全部线程,可以调用signalall()方法。如果想唤醒部分线程,可以实例化多个condition配合使用。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
浅析我对 String、StringBuilder、StringBuffer 的理解
使用IDEA搭建SSM框架的详细教程(spring + springMVC +MyBatis)
Springboot整合freemarker 404问题解决方案
引入mybatis-plus报 Invalid bound statement错误问题的解决方法
网友评论