Object中线程阻塞及唤醒方法使用
相关方法
挂起: wait()/wait(long timeout)/wait(long timeout, int nanos)
唤醒: notify()/notifyAll()
使用说明
调用对象的这些方法(wait/notify),必须先持有对象的监视器(monitor);否则会抛出IllegalMonitorStateException异常
例1:
public static void main(String[] args) { Thread th1 = new Thread(){ @Override public void run() { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } }; th1.start(); }
运行结果:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:503) at com.falco.src.verify.ObjectVerification$1.run(ObjectVerification.java:11)
当调用对象的wait方法后,线程处于阻塞状态,对应的监视器(monitor)也被释放,其他线程可以获得此监视器来唤醒该线程。当线程重新被唤醒时,它会再次获取该监视器(monitor),然后被唤醒
唤醒方式
调用wait方法后,线程处于阻塞状态。可以通过以下四种唤醒方式:
调用notify/notifyAll方法唤醒
例二:
public static void main(String[] args) { final Object bt = new Object(); Thread th1 = new Thread() { @Override public void run() { try { synchronized (bt) { bt.wait(); System.out.println("the thread has been woke up."); } } catch (InterruptedException e) { System.out.println("the current thread has been interupted."); e.printStackTrace(); } } }; th1.start(); Thread th2 = new Thread() { @Override public void run() { synchronized (bt) { bt.notify(); System.out.println("finish waking up."); } } }; th2.start(); System.out.println("wait the program exit."); }
结果:
wait the program exit. finish waking up. the thread has been woke up.
超时自动唤醒,即:wait方法指定一个超时时间,达到这个超时时间且没有被唤醒的线程将自动唤醒
例三:
public static void main(String[] args) { final Object bt = new Object(); Thread th1 = new Thread() { @Override public void run() { try { synchronized (bt) { bt.wait(10,1); System.out.println("the thread has been woke up."); } } catch (InterruptedException e) { System.out.println("the current thread has been interupted."); e.printStackTrace(); } } }; th1.start(); System.out.println("wait the program exit."); }
运行结果:
wait the program exit. the thread has been woke up.
中断唤醒,在其他线程中,调用阻塞线程的中断方法,从而唤醒阻塞的线程
例四:
public static void main(String[] args) { Thread th1 = new Thread() { @Override public void run() { try { synchronized (this) { this.wait(); } } catch (InterruptedException e) { System.out.println("the current thread has been interupted."); e.printStackTrace(); } } }; th1.start(); System.out.println("before interrupting,the interrupt flag:"+th1.isInterrupted()); th1.interrupt(); System.out.println("after interrupting,the interrupt flag:"+th1.isInterrupted()); }
运行结果:
before interrupting,the interrupt flag:false after interrupting,the interrupt flag:true the current thread has been interupted. java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:503) at com.falco.src.verify.ObjectVerification$1.run(ObjectVerification.java:11)
假醒(spurious wakeup),除了以上三种方式外,处于阻塞中的线程还可能自动被唤醒
由于假醒的存在,因此需要自行处理假醒的场景,通过下面的形式排出假醒,避免程序出错
... synchronized (bt) { while (condition) {//condition为不满足唤醒条件,即不满足唤醒条件时执行循环 bt.wait(); } } ...
假醒相关内容就不在这里介绍了,如果有兴趣,请自行研究
来源:https://www.cnblogs.com/falco/p/9382715.html