等待和通知

等待通知api一览

Java.lang.Object 类提供了一套等待通知的API,它由3个wait(),1个notify()和1个notifyAll()方法组成。

public final void wait(long timeout,

                       int nanos)

                throws InterruptedException

 

l  Void wait() : 导致当前线程一直处于等待,知道灵台的线程调用这个对象的notify()或者notifyAll(),又或者一直等待其他的线程中断当前等到的线程。

l  Void wait(long timeout): 外加等待timeout 毫秒数

l  Void wait(long timeout,int natos): 外加等待timeout 毫秒数 natos 纳秒数 

参数:
timeout - 要等待的最长时间(以毫秒为单位)。
nanos - 额外时间(以毫微秒为单位,范围是 0-999999)

抛出:
IllegalArgumentException - 如果超时值是负数,或者毫微秒值不在 0-999999 范围内。
IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。
InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的 中断状态 被清除。

 

 

l  Void notify(): 唤醒正在等待改对象监听的单挑线程。

l  Void notifyAll(): 唤醒正在等待改对象监听的全部线程。

对象在wait()时,线程会放弃对象关联的监听器的所有权。

 

警告:绝对不要在循环外调用wait()方法。

 

注意:notify()方法是从临界区中调用的,这个临界区和wait()方法所在的临界区一样,被同一个对象obj保护,并且也使用同一个对象来调用notify()。只要遵守这个模式,你就不会艳茹麻烦。

 

生产者和消费者

商店

/**

 * Project Name:demo

 * File Name:Shared.java

 * Package Name:tow

 * Date:2019年9月12日下午3:12:24

 * Copyright (c) 2019, 364574851@qq.com All Rights Reserved.

 *

*/

 

package tow;

 

/**

 * ClassName:Shared <br/>

 * Function: TODO ADD FUNCTION. <br/>

 * Reason: TODO ADD REASON. <br/>

 * Date: 2019年9月12日 下午3:12:24 <br/>

 *

 * @author zhangxdp

 * @version

 * @since JDK 1.8

 * @see

 */

public class Shared {

         private char c;

         private volatile boolean writeable = true;

 

         synchronized void setSharedChar(char ch) {

                   while (!writeable) {

                            try {

                                     wait();

                            } catch (Exception e) {

                                     // TODO: handle exception

                            }

                   }

                   this.c = ch;

                   writeable = false;

                   notify();

         }

 

         synchronized char getChar() {

                   while (writeable) {

                            try {

                                     wait();

                            } catch (Exception e) {

                                     // TODO: handle exception

                            }

                   }

                   writeable = true;

                   notify();

                   return c;

         }

 

}

 

生产者

/**

 * Project Name:demo

 * File Name:Produe.java

 * Package Name:tow

 * Date:2019年9月12日下午3:21:31

 * Copyright (c) 2019, 364574851@qq.com All Rights Reserved.

 *

*/

 

package tow;

 

/**

 * ClassName:Produe <br/>

 * Function: TODO ADD FUNCTION. <br/>

 * Reason: TODO ADD REASON. <br/>

 * Date: 2019年9月12日 下午3:21:31 <br/>

 *

 * @author zhangxdp

 * @version

 * @since JDK 1.8

 * @see

 */

public class Produe extends Thread {

         private final Shared d;

 

         Produe(Shared d) {

                   this.d = d;

         }

 

         @Override

         public void run() {

                   for (char ch = 'A'; ch < 'Z'; ch++) {

                            synchronized (d) {// 同步枷锁

                                     d.setSharedChar(ch);

                                     System.out.println(ch + " produced by zhang");

                            }

 

                   }

         }

 

}

 

消费者

/**

 * Project Name:demo

 * File Name:Consumer.java

 * Package Name:tow

 * Date:2019年9月12日下午3:26:25

 * Copyright (c) 2019, 364574851@qq.com All Rights Reserved.

 *

*/

 

package tow;

 

/**

 * ClassName:Consumer <br/>

 * Function: TODO ADD FUNCTION. <br/>

 * Reason: TODO ADD REASON. <br/>

 * Date: 2019年9月12日 下午3:26:25 <br/>

 *

 * @author zhangxdp

 * @version

 * @since JDK 1.8

 * @see

 */

public class Consumer extends Thread {

         private final Shared s;

 

         public Consumer(Shared s) {

                   this.s = s;

         }

 

         @Override

         public void run() {

                   char ch;

                   do {

                            synchronized (s) {// 同步枷锁

                                     ch = s.getChar();

                                     System.out.println(ch + " consumed by bengbeng");

                            }

                   } while (ch != 'Z');

         }

 

}

 

测试

/**

 * Project Name:demo

 * File Name:Test.java

 * Package Name:tow

 * Date:2019年9月12日下午3:30:00

 * Copyright (c) 2019, 364574851@qq.com All Rights Reserved.

 *

*/

 

package tow;

 

/**

 * ClassName:Test <br/>

 * Function: TODO ADD FUNCTION. <br/>

 * Reason: TODO ADD REASON. <br/>

 * Date: 2019年9月12日 下午3:30:00 <br/>

 *

 * @author zhangxdp

 * @version

 * @since JDK 1.8

 * @see

 */

public class Test {

 

         public static void main(String[] args) {

                   Shared s = new Shared();

                   new Produe(s).start();

                   new Consumer(s).start();

         }

}

 

 

这个是同步枷锁处理,打印结果

 

 

如果去掉同步枷锁,可能出现如下结果:

 

 

下面以消费者执行的场景进行演示:

    1. 消费者执行s.getChar()方法来索取一个字母。
    2. 在同步方法中,由于writeable=true,所以执行wai()等待。现在消费者会一直等待,知道收到来自生产者的通知。
    3. 生产者最终执行s.setChar(ch)方法。
    4. 生产者进入同步方法中,他发现writeable=true,便不会调用wait()方法。
    5. 生产者保存下这个字母,把writeable=false,并调用notify()方法唤醒消费者。
    6. 生产者退出setChar(ch)方法。
    7. 消费者醒来,把writeable=true,通知唤醒生产者线程,并返回共享的字母。

posted on 2019-09-12 16:10  不在是从前  阅读(112)  评论(0)    收藏  举报

导航