虹口建设机械网站制作,怎么进入外网,网站建设协议 模板下载,企业网站东莞网站建设制作java#xff1a;线程等待与唤醒 - Object的wait()和notify()
1 前言
java使用Object类的wait()和notify()方法#xff0c;可以实现线程等待和唤醒#xff08;Object类为所有类的父类#xff0c;即所有类天然具有线程等待和唤醒的方法#xff0c;一般使用Object类的wait(…java线程等待与唤醒 - Object的wait()和notify()
1 前言
java使用Object类的wait()和notify()方法可以实现线程等待和唤醒Object类为所有类的父类即所有类天然具有线程等待和唤醒的方法一般使用Object类的wait()和notify()方法即可。
使用wait()、notify()时有一些注意点比如wait和notify方法需在同步代码块synchronized 代码块或方法方法包含锁实例对象的synchronized实例方法以及锁类对象的synchronized static方法中使用一般成对出现。
在一般执行时还具有先后顺序的强依赖即先执行wait再执行notify若先执行notify再执行wait后续无线程唤醒操作时阻塞的线程将无法被唤醒。
2 使用
使用前先关注下java文档中的说明
* This method should only be called by a thread that is the owner
* of this objects monitor. A thread becomes the owner of the
* objects monitor in one of three ways:
* ul
* liBy executing a synchronized instance method of that object.
* liBy executing the body of a {code synchronized} statement
* that synchronizes on the object.
* liFor objects of type {code Class,} by executing a
* synchronized static method of that class.
* /ul* Only one thread at a time can own an objects monitor.
*
* throws IllegalMonitorStateException if the current thread is not
* the owner of this objects monitor.
* see java.lang.Object#notifyAll()
* see java.lang.Object#wait()
public final native void notify();* This method should only be called by a thread that is the owner
* of this objects monitor. See the {code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
* throws IllegalMonitorStateException if the current thread is not
* the owner of the objects monitor.
* throws InterruptedException if any thread interrupted the
* current thread before or while the current thread
* was waiting for a notification. The iinterrupted
* status/i of the current thread is cleared when
* this exception is thrown.
* see java.lang.Object#notify()
* see java.lang.Object#notifyAll()
*/
public final void wait() throws InterruptedException {wait(0);
}上述表明notify执行时若当前线程不是Object的monitor的持有者则抛出IllegalMonitorStateException。
判断是否当前线程持有Object的monitor即上述提到的3个方式要么在synchronized代码块中执行object.wait()或object.notify()要么就是synchronized实例方法此时synchronized锁对象为实例对象若是synchronized static 方法则synchronized锁对象为类对象注意不同方式使用不同的锁对象即可此3种方式表示当前线程为Object的monitor持有者可以顺利执行wait()或notify()方法反之则抛出IllegalMonitorStateException。
常见的使用方式如下
public class TestObjectWaitAndNotify {private Object lockObj new Object();private void doSubmit(){System.out.println(成功提交!);}public void run() throws Exception{AtomicBoolean f new AtomicBoolean(false);new Thread(() - {synchronized (this.lockObj){System.out.println(Thread.currentThread().getName() 开始执行);while(!f.get()){try {this.lockObj.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() 执行结束);doSubmit();}}, xiaoxu1).start();TimeUnit.SECONDS.sleep(2);new Thread(() - {synchronized (this.lockObj){System.out.println(Thread.currentThread().getName() 开始执行);f.set(true);this.lockObj.notify();System.out.println(Thread.currentThread().getName() 执行结束);}}, xiaoxu2).start();}public static void main(String[] args) throws Exception{TestObjectWaitAndNotify n new TestObjectWaitAndNotify();n.run();}
}执行结果如下
xiaoxu1开始执行
xiaoxu2开始执行
xiaoxu2执行结束
xiaoxu1执行结束
成功提交!上述执行时因为对象的监视器monitor含有该对象的锁、阻塞队列和同步队列执行lockObj.wait()时除了使当前线程进入阻塞队列还需要释放锁否则后续执行synchronized (this.lockObj)的第二个线程无法获取到锁并执行唤醒操作然后后续休眠2秒后第二个线程执行synchronized (this.lockObj)再次获取到锁锁需是同一个对象的monitor持有的锁执行唤醒操作即阻塞队列中的休眠线程被再次唤醒并执行执行后续的doSubmit()且因为标志位改变故而不再发起wait整个过程结束。
另Object.notifyAll()方法即唤醒当前阻塞队列的全部休眠线程唤醒操作意即notify、notifyAll会将阻塞队列中的线程放入同步队列中等待执行同时竞争锁失败的线程也会放入同步队列中等待同步执行。
注意上述线程的等待和唤醒操作因为加锁synchronized决定了第一个线程会先于第二个线程获取到锁和代码顺序故而是先等待再唤醒若代码顺序为先唤醒再等待即便操作都加上synchronized加上synchronized保证了wait先执行notify后执行但因为代码操作顺序改变阻塞队列没有休眠线程此时再次执行wait线程1将被一直阻塞无法唤醒。故wait()和notify()具有先后执行顺序的强依赖关系。