等待和通知
等待通知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 纳秒数
|
参数: 抛出:
|
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(); } } |
这个是同步枷锁处理,打印结果
如果去掉同步枷锁,可能出现如下结果:
下面以消费者执行的场景进行演示:
- 消费者执行s.getChar()方法来索取一个字母。
- 在同步方法中,由于writeable=true,所以执行wai()等待。现在消费者会一直等待,知道收到来自生产者的通知。
- 生产者最终执行s.setChar(ch)方法。
- 生产者进入同步方法中,他发现writeable=true,便不会调用wait()方法。
- 生产者保存下这个字母,把writeable=false,并调用notify()方法唤醒消费者。
- 生产者退出setChar(ch)方法。
- 消费者醒来,把writeable=true,通知唤醒生产者线程,并返回共享的字母。
浙公网安备 33010602011771号