Java 高并发程序设计学习笔记--wait 和notify

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34503659/article/details/79164332

等待(wait) 和 通知(notify)

说明: 文本是学习了《Java 高并发程序设计》中的等待和通知内容的学习笔记,结合实例总结了一些小结论。

wait () 方法顾名思义就是线程处于等待状态,当程序执行遇到synchronize同步块时,线程会进入BLOCKED阻塞状态,此时线程暂时停止执行知道获取到请求锁。当调用wait方法时,线程就会进入WAITING状态,知道等待到一个notify方法,线程就会重新执行。提到wait,join方法也是等待方法,两者的区别是wait等到notify就会继续执行,而join会等到目标线程终止。

wait和notify的使用,这两个方法不是Thread类中的方法,而是输入的Object对象的方法,如果线程A调用了object.wait,那么线程A会处于等待状态,直到其他线程调用了object.notify,A才会继续执行。

下面是一个简单的小例子:

    private static Object object = new Object();
    public static class T1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                try {
                    System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getId() + "  T1 start ");
                    System.out.println("T1 wait 1");
                    object.wait();

                } catch (InterruptedException e) {
                    System.out.println("T1 InterruptedException");
                }
                System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getId() +" T1 end!");

            }
        }
    }
    public static class T2 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                try {
                    System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getId() + " T2 start ");
                    System.out.println(" T2 notify");
                    object.notify();
                    Thread.sleep(3000);

                } catch (InterruptedException e) {
                    System.out.println("T2 InterruptedException");
                }
                System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getId() +" T2 end!");
            }
        }
    }


    public static void main(String[] args) throws Exception{
        new T1().start();
        new T2().start();
    }

执行的结果是:
这里写图片描述

根据控制台输出的结果可以看出,当T2调用了object.notify()后,T1并没有立即执行,而是等待T2执行完之后,T1才获取到锁,重新继续执行。

如果在T1中调用两次wait,T2中notify两次,T1会end么?

public static class T1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                try {
                    System.out.println(System.currentTimeMillis() + " : threadId:" + Thread.currentThread().getId() + " T1 start ");
                    System.out.println("T1 第一次wait 1");
                    object.wait();
                    System.out.println(System.currentTimeMillis() + " : T1 第二次 wait 2");
                    object.wait();

                } catch (InterruptedException e) {
                    System.out.println("T1 InterruptedException");
                }
                System.out.println(System.currentTimeMillis() + " : threadId:" + Thread.currentThread().getId() +" T1 end!");

            }
        }
    }
    public static class T2 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                try {
                    System.out.println(System.currentTimeMillis() + " : threadId:" + Thread.currentThread().getId() + " T2 start ");
                    System.out.println("T2 第一次notify");
                    object.notify();
                    Thread.sleep(3000);
                    System.out.println("T2 第二次notify");
                    object.notify();
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    System.out.println("T2 InterruptedException");
                }
                System.out.println(System.currentTimeMillis() + " : threadId:" + Thread.currentThread().getId() +" T2 end!");
            }
        }
    }

此时的结果如下:
这里写图片描述

如图所示,T1第一次wait是在T2结束之后被通知的,第二次wait一直处于等待状态。
如何将T1执行结束呢?

 public static class T2 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                try {
                    System.out.println(System.currentTimeMillis() + " : threadId:" + Thread.currentThread().getId() + " T2 start ");
                    System.out.println("T2 第一次notify");
                    object.notify();
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    System.out.println("T2 InterruptedException");
                }
                System.out.println(System.currentTimeMillis() + " : threadId:" + Thread.currentThread().getId() +" T2 end!");
            }
        }
    }
  public static void main(String[] args) throws Exception{
        new T1().start();
        new T2().start();
        new T2().start();
        // 或者第二中方式
        new T1().start();
        new T2().start();
        Thread.sleep(5000);
        synchronized (object) {
            System.out.println(System.currentTimeMillis() + "  object.notify()");
            object.notify();
        }

    }

结果如下:
这里写图片描述

第二中方式的结果如下:
这里写图片描述

如图,当新创建一个T2时,T1可以继续执行知道End。

当T1调用object.wait 时,object的锁被释放,T2调用object.notify时获取到object的锁,当T2执行完之后释放了object锁,此时T1获取到了object的锁,继续程序。第二个例子中,将T1调用了两次wait,T2调用了两次notify,但是T1没有继续执行,而是停在了第二次wait,由于T2执行结束,所以T1第一次等待被唤醒,第二次等待由于T2已经完成所以第二次的wait获取不到notify的唤醒,一直处于等待状态。

第三个例子中,重新new了一个T2,此时的T2和第一次New的T2是两个完全不用的线程。从结果也可以看出,当id为13的线程结束是T1才结束,也就是说T1的第二个wait是id为13的线程唤醒的。

猜你喜欢

转载自blog.csdn.net/qq_34503659/article/details/79164332