Java多线程基础 线程的等待与唤醒(wait、notify、notifyAll)
本篇我们来研究一下wait()notify()notifyAll()。
DEMO1:wait()与notify()
publicclassTest{ staticclassThreadOneextendsThread{ privateCallbackmCallback; @Override publicvoidrun(){ work(); if(mCallback!=null){ mCallback.onResult(false); } } //耗时3s privatevoidwork(){ System.out.println("正在查询数据库1"); longstartTime=System.currentTimeMillis(); while(true){ if(System.currentTimeMillis()-startTime<3000){ continue; } break; } } publicvoidsetCallback(Callbackcallback){ mCallback=callback; } publicinterfaceCallback{ voidonResult(booleanresult); } } staticclassThreadTestextendsThread{ privateObjectmLock=newObject(); privateThreadOnemThreadOne; @Override publicvoidrun(){ workOne(); System.out.println("根据结果继续做其他事情"); } privatevoidworkOne(){ mThreadOne=newThreadOne(); mThreadOne.setCallback(newThreadOne.Callback(){ @Override publicvoidonResult(booleanresult){ System.out.println("查询数据库1结束,:"+(result?"有数据":"无数据")); synchronized(mLock){ mLock.notify(); System.out.println("--ThreadTest结束等待--"); } } }); mThreadOne.start(); try{ synchronized(mLock){ System.out.println("--ThreadTest进入等待--"); mLock.wait(); } }catch(InterruptedExceptione){ e.printStackTrace(); } } } publicstaticvoidmain(String[]var0){ ThreadTestthreadTest=newThreadTest(); threadTest.start(); } }
DEMO1输出:
--ThreadTest进入等待-- 正在查询数据库1 查询数据库1结束,:无数据 --ThreadTest结束等待-- 根据结果继续做其他事情
注意:
使用wait()和notify()必须在获得同步锁后才能调用,若直接调用会报java.lang.IllegalMonitorStateException错误,因为状态由同步锁保护。
wait()不同于sleep()的是wait()会释放同步锁。
因为wait()和notify()是基于同步锁实现的,每个对象都有自己的同步锁,所以wait()和notify()是Object的方法,而不是Thread。
DEMO2,wait()与notifyAll():
publicclassTest{ privatestaticObjectmLock=newObject(); staticclassMyThreadextendsThread{ StringmName; CallbackmCallback; publicMyThread(Stringname){ mName=name; } @Override publicvoidrun(){ work(); if(mCallback!=null){ mCallback.onResult(false); } } //耗时3s privatevoidwork(){ System.out.println(mName+"等待"); try{ synchronized(mLock){ mLock.wait(); } }catch(InterruptedExceptione){ e.printStackTrace(); } } publicvoidsetCallback(Callbackcallback){ mCallback=callback; } publicinterfaceCallback{ voidonResult(booleanresult); } } staticclassThreadTestextendsThread{ @Override publicvoidrun(){ work("db1"); work("db2"); work("db3"); try{ sleep(2000); }catch(InterruptedExceptione){ e.printStackTrace(); } synchronized(mLock){ System.out.println("唤醒全部"); mLock.notifyAll(); } } privatevoidwork(Stringname){ finalMyThreadmyThread=newMyThread(name); myThread.setCallback(newMyThread.Callback(){ @Override publicvoidonResult(booleanresult){ System.out.println(myThread.mName+"回来了"); } }); myThread.start(); } } publicstaticvoidmain(String[]var0){ ThreadTestthreadTest=newThreadTest(); threadTest.start(); } }
DEMO2输出:
db1等待
db3等待
db2等待
唤醒全部
db3回来了
db1回来了
db2回来了
同一个对象的wait()方法可多次在不同的线程中调用,可让不同的线程进入等待(阻塞),可以一个一个notify(),也可以调用notifyAll()一次性全部唤醒。