乐趣区

java并发编程学习之线程的生命周期waitnotifynotifyall六

sleep 和 wait

  1. sleep 是 Thread 类的方法,wait 是 Object 的方法。
  2. sleep 可以到处使用,wait 必须是在同步方法或者代码块里使用,不然会有 java.lang.IllegalMonitorStateException 异常。
  3. sleep 不释放持有的锁,wait 释放锁。wait 在调用方法前,必须持有锁,调用 notify,notifyall 唤醒,也要持有锁。
  4. sleep 休眠一定时间后,进入就绪状态。wait 由 notify 和 notifyall 唤醒。这两个都能被 interrupt 方法中断当前状态。

join 和 yield

这两个和 sleep 一样,不释放持有的锁。

示例

public class WaitDemo {
    private String tv = "广告";

    static class Tv extends Thread {
        WaitDemo waitDemo;

        public Tv(WaitDemo waitDemo) {this.waitDemo = waitDemo;}

        @Override
        public void run() {waitDemo.waitTv();
        }
    }

    public synchronized void waitTv() {while (tv.equals("广告")) {
            try {wait();
                if (tv.equals("广告")) {System.out.println(Thread.currentThread().getName() + "-" + "骗人,还是广告");
                }
            } catch (InterruptedException e) {e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + "-" +"愉快的追剧");
    }

    public synchronized void sendTrueMsg() {
        tv = "正剧";
        notifyAll();}

    public synchronized void sendFalseMsg() {notifyAll();
    }

    public static void main(String[] args) throws InterruptedException {WaitDemo waitDemo = new WaitDemo();
        Tv tv1 = new Tv(waitDemo);
        Tv tv2 = new Tv(waitDemo);
        tv1.start();
        tv2.start();
        Thread.sleep(100);
        waitDemo.sendFalseMsg();
        Thread.sleep(100);
        waitDemo.sendTrueMsg();}
}

运行的结果如下:

例子:大部分人喜欢看连续剧,但是不看广告(没钱买 VIP),于是就让别人提醒她广告结束了没有,如果结束了,就提醒她。
用法:

wait 方

  1. 获取锁
  2. while 判断条件,不满足继续 wait
  3. 满足执行其他业务

notify 方

  1. 获取锁
  2. 改变条件
  3. 通知

为什么是 while 而不是 if

while 会一直循环,直到条件满足。如果是 if,只会判断一次,如果不满足条件,会一直等待

为什么是 notifyAll 而不是 notify

可以把上面的例子,改成 notify,那么进程永远不会结束,因为在多线程情况下,notify 只能唤醒随机的一个休眠线程,其他已休眠的线程不能唤醒,造成信号不能传达而丢失,而 notifyAll 可以唤醒所有的。

退出移动版