public class WaitTest {
    //wait,notify方法
    //wait,notify方法在使用的时候有两个注意事项:1.线程的阻塞与唤醒是通过锁来实现的;即使用锁来调用wait,notify方法;2这种方式,必须要求
    //锁对象在这个线程之中,并且一个线程必须拥有这把锁才有资格对锁操作,即谁持有锁,谁能操作锁。
    public static final Object MONITOR = new Object();

    public static void main(String[] args) {
        new Thread(()-> {
            synchronized (MONITOR){
                System.out.println("线程1开始了");
                try {
                    MONITOR.wait();//注意Monitor的等待和唤醒方法必须在持有的线程之中,即谁持有这把锁,谁才能操作这把锁;
                    //wait(10)如果没人唤醒我,会在时间结束后唤醒字节
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1结束了");
            }
        }).start();
        new Thread(()-> {
            synchronized (MONITOR){
                System.out.println("线程2开始了");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                MONITOR.notify();//使用锁来唤醒想要持有这个锁的线程,并且时随机的.notifyAll则是唤醒所有的线程。
                //notifyAll,会唤醒争抢锁的所有线程,让这些线程争抢,争抢上的持有这个锁。

                System.out.println("线程2结束了");

            }
        }).start();


        //这段代码的作用就是,线程1开始了先打印,打印完成由于线程1 被wait了,所以线程1结束了就不会被打印;
        //线程2开始了被打印,过了两秒之后,接着线程2使用锁唤醒了线程1,线程1结束了就会被打印
        //线程的阻塞和唤醒是由锁对象来实现的
        
    }
    //wait()方法与sleep方法的区别:正如上面的代码,线程1首先占用了锁MONITOR,并且打印了“线程1开始了”,执行之后,MONITOR.wait()。方***立刻释放锁资源,于是线程2会得到锁MONITOR,于是打印了“线程2开始了”,并且使用了sleep2秒,但是sleep不会释放锁,但是由于线程2,使用了MONITOR
    //.notify()函数唤醒了线程1.接着答应线程2结束了,线程2结束了之后会释放锁MONITOR于是线程1。
    
    //wait,sleep都会释放CPU的计算资源,但是wait方式会将CPU释放了,锁资源也同时释放了。

}