java wait 和 notify实现线程间通信

今天同学问我一个问题,为什么他执行的代码不会结束,代码如下:

public class TestAccount {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Account acc = new Account();
        new Thread(acc).start();
        new Thread(acc).start();
    }

}

class Account implements Runnable {

    int balance = 0;

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 3; i++) {
            synchronized (this) {
                notify();
                balance += 1000;
                System.out.println(Thread.currentThread().getName() + "存入1000元,账户余额为:" + balance);
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

其运行结果如下:

Thread-0存入1000元,账户余额为:1000
Thread-1存入1000元,账户余额为:2000
Thread-0存入1000元,账户余额为:3000
Thread-1存入1000元,账户余额为:4000
Thread-0存入1000元,账户余额为:5000
Thread-1存入1000元,账户余额为:6000

从代码里可以看出,一个有两个线程,共享一个对象,也就是多线程编程的问题,多线程操作一个共享变量,使用了同步代码块来实现的并发编程。其实,代码没有结束的原因很简单,就是Thread-1在最后一次执行后,调用了wait方法,还在那等待,所以程序始终没有结束。

注意点

这里要注意的就是,notify()调用后,并不是马上就释放对象锁的,而是在相应的同步块或同步方法中执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。所以说,在同步代码块或者同步方法上,notify放在哪个位置其实没有什么影响。

流程分析

1.

开始,线程0和线程1都执行了,但是因为线程0获得了锁,所以线程1被阻塞, 线程0 执行完 balance += 1000;后打印1000,调用wait,释放锁同时也释放cpu资源,最后调用notify,此时线程1收到唤醒通知。

此时线程0的i=0

2.

线程1收到通知后,然后获得锁,执行完balance += 1000;后打印2000,然后调用wait,释放锁同时也释放cpu资源,最后调用notify,此时线程0收到唤醒通知。

此时线程1的i=0

3.

线程0收到通知后,然后获得锁,执行完balance += 1000;后打印3000,然后调用wait,释放锁同时也释放cpu资源,最后调用notify,此时线程1收到唤醒通知。

此时线程0的i=1

4.

线程1收到通知后,然后获得锁,执行完balance += 1000;后打印4000,然后调用wait,释放锁同时也释放cpu资源,最后调用notify,此时线程0收到唤醒通知。

此时线程1的i=1

5.

线程0收到通知后,然后获得锁,执行完balance += 1000;后打印5000,然后调用wait,释放锁同时也释放cpu资源,最后调用notify,此时线程1收到唤醒通知。

此时线程0的i=2

6.

线程1收到通知后,然后获得锁,执行完balance += 1000;后打印6000,然后调用wait,释放锁同时也释放cpu资源,最后调用notify,此时线程0收到唤醒通知。

此时线程1的i=2

7.

线程0收到通知后,被唤醒,然后执行i++之后i=3,然后执行for循环后,发现不符合循环条件,最后跳出for循环,线程0执行完毕。
 然而,因为线程0执行完毕,线程1永远也收不到通知,所以线程1一直在等待,所以这就是程序永远不会终止的原因所在。

你可能感兴趣的:(java wait 和 notify实现线程间通信)