( 1 )等待唤醒机制就是用于解决线程间通信的问题的,使用到的3个方法的含义如下:
wait:告诉当前线程放弃执行权,并放弃监视器(锁)并进入阻塞状态,直到其他线程持有获得执行权,并持有了相同的监视器(锁)并调用notify为止。
notify:唤醒持有同一个监视器(锁)中调用wait的第一个线程,例如,餐馆有空位置后,等候就餐最久的顾客最先入座。注意:被唤醒的线程是进入了可运行状态。等待cpu执行权。
notifyAll:唤醒持有同一监视器中调用wait的所有的线程。
( 2 )调用wait和notify方法需要注意的细节:
wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程。
wait方法与notify方法是属于Object类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Object类的。
wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方法。
( 3 ) waite和sleep方法的区别
1.相同之处:
线程调用wait()或者是sleep()方法都会进入临时阻塞状态,会释放cpu的执行权。调用时都需要处理 InterruptedException异常。
2.不同之处:
wait(): 释放资源,释放锁。是Object的方法。
sleep():释放资源,不释放锁。是Thread的静态方法
下面通过例子来说明.
- /**
- * 要实现的效果就是,有一个水池,水池的容量为50L,一个放水线程,负责放水,每200毫秒放出1L水,当水放完后,通知注水线程工作,同时放水线程停止工作;
- * 注水线程每200毫秒注水1L,水注满时,再通知放水线程继续工作,同时注水线程停止工作.
- *
- * @author mChenys
- *
- */
- public class _Main5 {
- public static void main(String[] args) {
- Pool pool = new Pool();
- WaterIn in = new WaterIn(pool, "注水线程");
- WaterOut out = new WaterOut(pool, "放水线程");
- in.start();
- out.start();
- }
- }
- /**
- * 水池,容量为50L
- *
- * @author mChenys
- *
- */
- class Pool {
- public int MAX_VLAUE = 50;
- public int curr_value = 0;
- }
- /**
- * 注水线程
- *
- * @author mChenys
- *
- */
- class WaterIn extends Thread {
- private Pool pool;
- public WaterIn(Pool pool, String name) {
- super(name);
- this.pool = pool;
- }
- @Override
- public void run() {
- while (true) {
- synchronized (pool) {
- try {
- if (pool.curr_value < pool.MAX_VLAUE) {
- // 加水
- Thread.sleep(200);
- pool.curr_value += 1;
- System.out.println(this.getName() + "正在加水,加入 "
- + pool.curr_value + " L水");
- } else if (pool.curr_value == pool.MAX_VLAUE) {
- System.out.println(this.getName()
- + "水已加满!!,可以放水了......");
- pool.notify();// 唤醒放水线程
- pool.wait();// 当前线程等待,释放锁对象
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- /**
- * 放水线程
- *
- * @author mChenys
- *
- */
- class WaterOut extends Thread {
- private Pool pool;
- public WaterOut(Pool pool, String name) {
- super(name);
- this.pool = pool;
- }
- @Override
- public void run() {
- while (true) {
- synchronized (pool) {
- try {
- if (pool.curr_value > 0) {
- // 放水
- Thread.sleep(200);
- pool.curr_value -= 1;
- System.out.println(this.getName() + "开始放水,放出 "
- + (pool.MAX_VLAUE - pool.curr_value) + " L水");
- } else if (pool.curr_value == 0) {
- System.out.println(this.getName() + "水已放完,可以加水了.....");
- pool.notify();// 唤醒注水线程
- pool.wait();// 当前线程等待,释放锁对象
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- 注水线程正在加水,加入 20 L水
- 注水线程正在加水,加入 40 L水
- 注水线程正在加水,加入 60 L水
- 注水线程正在加水,加入 80 L水
- 注水线程正在加水,加入 100 L水
- 注水线程正在加水,加入 120 L水
- 注水线程正在加水,加入 140 L水
- 注水线程正在加水,加入 160 L水
- 注水线程正在加水,加入 180 L水
- 注水线程正在加水,加入 200 L水
- 注水线程正在加水,加入 220 L水
- 注水线程正在加水,加入 240 L水
- 注水线程正在加水,加入 260 L水
- 注水线程正在加水,加入 280 L水
- 注水线程正在加水,加入 300 L水
- 注水线程正在加水,加入 320 L水
- 注水线程正在加水,加入 340 L水
- 注水线程正在加水,加入 360 L水
- 注水线程正在加水,加入 380 L水
- 注水线程正在加水,加入 400 L水
- 注水线程正在加水,加入 420 L水
- 注水线程正在加水,加入 440 L水
- 注水线程正在加水,加入 460 L水
- 注水线程正在加水,加入 480 L水
- 注水线程正在加水,加入 500 L水
- 注水线程水已加满!!,可以放水了......
- 放水线程开始放水,放出 20 L水
- 放水线程开始放水,放出 40 L水
- 放水线程开始放水,放出 60 L水
- 放水线程开始放水,放出 80 L水
- 放水线程开始放水,放出 100 L水
- 放水线程开始放水,放出 120 L水
- 放水线程开始放水,放出 140 L水
- 放水线程开始放水,放出 160 L水
- 放水线程开始放水,放出 180 L水
- 放水线程开始放水,放出 200 L水
- 放水线程开始放水,放出 220 L水
- 放水线程开始放水,放出 240 L水
- 放水线程开始放水,放出 260 L水
- 放水线程开始放水,放出 280 L水
- 放水线程开始放水,放出 300 L水
- 放水线程开始放水,放出 320 L水
- 放水线程开始放水,放出 340 L水
- 放水线程开始放水,放出 360 L水
- 放水线程开始放水,放出 380 L水
- 放水线程开始放水,放出 400 L水
- 放水线程开始放水,放出 420 L水
- 放水线程开始放水,放出 440 L水
- 放水线程开始放水,放出 460 L水
- 放水线程开始放水,放出 480 L水
- 放水线程开始放水,放出 500 L水
- 放水线程水已放完,可以加水了.....
- 注水线程正在加水,加入 20 L水
- 注水线程正在加水,加入 40 L水
- 注水线程正在加水,加入 60 L水
- 注水线程正在加水,加入 80 L水
- 注水线程正在加水,加入 100 L水
- 注水线程正在加水,加入 120 L水
- 注水线程正在加水,加入 140 L水
- 注水线程正在加水,加入 160 L水
- 注水线程正在加水,加入 180 L水
- 注水线程正在加水,加入 200 L水
- 注水线程正在加水,加入 220 L水
- 注水线程正在加水,加入 240 L水
- 注水线程正在加水,加入 260 L水
- 注水线程正在加水,加入 280 L水
- 注水线程正在加水,加入 300 L水
- 注水线程正在加水,加入 320 L水
- 注水线程正在加水,加入 340 L水
- 注水线程正在加水,加入 360 L水
- 注水线程正在加水,加入 380 L水
- 注水线程正在加水,加入 400 L水
- 注水线程正在加水,加入 420 L水
- 注水线程正在加水,加入 440 L水
- 注水线程正在加水,加入 460 L水
- 注水线程正在加水,加入 480 L水
- 注水线程正在加水,加入 500 L水
- 注水线程水已加满!!,可以放水了......
- 放水线程开始放水,放出 20 L水
- 放水线程开始放水,放出 40 L水
- 放水线程开始放水,放出 60 L水
- 放水线程开始放水,放出 80 L水
- 放水线程开始放水,放出 100 L水
- 放水线程开始放水,放出 120 L水
- 放水线程开始放水,放出 140 L水
- 放水线程开始放水,放出 160 L水
- 放水线程开始放水,放出 180 L水
- 放水线程开始放水,放出 200 L水