模式之保护性暂停
作者:互联网
优雅地使用wait/notify
什么时候适合使用wait
- 当线程不满足某些条件,需要暂停运行时,可以使用wait。这样会将对象的锁释放,让其他线程能够继续运行。如果此时使用sleep,会导致所有线程都进入阻塞,导致所有线程都没法运行,直到当前线程sleep结束后,运行完毕,才能得到执行。
使用wait/notify需要注意什么
- 当有多个线程在运行时,对象调用了wait方法,此时这些线程都会进入WaitSet中等待。如果这时使用了notify方法,可能会造成虚假唤醒(唤醒的不是满足条件的等待线程),这时就需要使用notifyAll方法
synchronized (LOCK) { while(//不满足条件,一直等待,避免虚假唤醒) { LOCK.wait(); } //满足条件后再运行 } synchronized (LOCK) { //唤醒所有等待线程 LOCK.notifyAll(); }
public class Test2 { public static void main(String[] args) { String hello = "hello thread!"; Guarded guarded = new Guarded(); new Thread(()->{ System.out.println("想要得到结果"); synchronized (guarded) { System.out.println("结果是:"+guarded.getResponse()); } System.out.println("得到结果"); }).start(); new Thread(()->{ System.out.println("设置结果"); synchronized (guarded) { guarded.setResponse(hello); } }).start(); } } class Guarded { /** * 要返回的结果 */ private Object response; //优雅地使用wait/notify public Object getResponse() { //如果返回结果为空就一直等待,避免虚假唤醒 while(response == null) { synchronized (this) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } return response; } public void setResponse(Object response) { this.response = response; synchronized (this) { //唤醒休眠的线程 this.notifyAll(); } } @Override public String toString() { return "Guarded{" + "response=" + response + '}'; } }
join源码——使用保护性暂停模式
只要线程一直alive 就一直等待 即使其他对象释放锁 notify 了 它也拿不到锁
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
标签:guarded,synchronized,模式,保护性,public,线程,暂停,response,wait 来源: https://www.cnblogs.com/licncnn/p/16068510.html