多线程间的通信 wait()、notify()、notifyAll()

多线程如何进行线程间的通信

测试代码:

// class Service
public class Service {

    public void testMethod(Object lock) {
        try{
            synchronized (lock) {
                System.out.println("begin wait() ThreadName="
                        + Thread.currentThread().getName());
                lock.wait();
                System.out.println("end wait() ThreadName="
                        + Thread.currentThread().getName());
            }
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }

}
// class ThreadA
public class ThreadA extends Thread{
    private Object lock;

    public ThreadA(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service s = new Service();
        s.testMethod(lock);
    }
}
// class ThreadB
public class ThreadB  extends Thread{
    private Object lock;

    public ThreadB(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service s = new Service();
        s.testMethod(lock);
    }
}
// class ThreadC
public class ThreadC  extends Thread{
    private Object lock;

    public ThreadC(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service s = new Service();
        s.testMethod(lock);
    }
}
// class NotifyThread
public class NotifyThread extends Thread{
    private Object lock;

    public NotifyThread(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            lock.notify();
//          lock.notify();
//          lock.notify();
//          lock.notify();
//          lock.notifyAll();
        }
    }
}
// class Main
public class Main {

    public static void main(String[] args) {
        service();
    }

    private static void service() {
        try{
            Object lock = new Object();
            ThreadA ta = new ThreadA(lock);
            ta.start();
            ThreadB tb = new ThreadB(lock);
            tb.start();
            ThreadC tc = new ThreadC(lock);
            tc.start();
            Thread.sleep(3000); // 主线程睡眠3秒钟
            NotifyThread notifyThread = new NotifyThread(lock);
            notifyThread.start();

        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }

}

输出结果(程序还在执行状态,并没有退出,因为还有两个线程处于等待状态):

begin wait() ThreadName=Thread-0
begin wait() ThreadName=Thread-1
begin wait() ThreadName=Thread-2
end wait() ThreadName=Thread-0

从以上输出中我们可以得知Thread-0首先获得了lock对象的对象锁,然后执行到lock.wait()后,Thread-0线程进入等待状态并释放了lock对象的对象锁、然后是Thread-1、Thread-2线程依次执行Thread-0的步骤。最后三个线程均进入等待状态并将lock对象的对象锁释放掉。主线程在等待了三秒后创建了notifyThread对象并新创建了一个线程,notifyThread线程获取lock对象的对象锁后执行lock.notify()方法随机唤醒三个等待线程中的一个(从打印结果看出随机唤醒的是Thread-0),被唤醒的线程继续执行lock.wait()后续代码,直至该线程的任务执行完毕。

结论:notify一次只能随机唤醒一个在等待的线程,如果存在多个等待线程,其他没被唤醒的线程会继续等待下去。

将NotifyThread的run方法内的lock.notify()全部解开注释,如下:

@Override
public void run() {
    synchronized (lock) {
        lock.notify();
        lock.notify();
        lock.notify();
        lock.notify();
//      lock.notifyAll();
    }
}

执行后的输出结果:

begin wait() ThreadName=Thread-0
begin wait() ThreadName=Thread-1
begin wait() ThreadName=Thread-2
end wait() ThreadName=Thread-0
end wait() ThreadName=Thread-2
end wait() ThreadName=Thread-1

从以上输出结果可以看出,虽然执行了四次lock.notify()方法,但是只有三个线程处于等待状态,多次执行lock.notify()会被系统自动忽略。每次执行完lock.notify()方法后都会随机唤醒一个处于等待状态的线程。

我们将NotifyThread的run方法内的lock.notify();方法全部注释掉,解开lock.notifyAll();的注释代码,如下所示:

@Override
public void run() {
    synchronized (lock) {
//      lock.notify();
//      lock.notify();
//      lock.notify();
//      lock.notify();
        lock.notifyAll();
    }
}

再次执行后输出如下:

begin wait() ThreadName=Thread-0
begin wait() ThreadName=Thread-2
begin wait() ThreadName=Thread-1
end wait() ThreadName=Thread-1
end wait() ThreadName=Thread-2
end wait() ThreadName=Thread-0

从以上结果可以看出,lock.notifyAll()方法会将所有处于等待的线程全部唤醒,也就不需要去关心有多少线程处于等待状态了。

通过wait()和notify(),notifyAll()方法可以实现线程件的通信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值