多线程通信(一)wait/notify

本文详细介绍了Java中多线程通信的基本原理及其实现方式,重点讲解了wait/notify机制,包括wait/notify的基本用法、注意事项以及如何正确地使用它们来避免线程间的竞争条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        线程是系统运行中的一个独立的子任务,这些子任务经过程序的处理构成了一个完整的任务,而这些子任务之间能够相互通信是构成完整任务不可缺少的一部分。使用多线程通信,可以在执行程序的时候大大提高CPU的使用效率。

        那么多线程通信的方式有哪些呢,现在由基本的开始说起。

        wait/notify方法(使用等待/通知机制实现多线程通信)

         wait()方法是Object类的方法,它的作用是使当前正在执行代码的线程进行等待,并释放对象锁,并停在wait()代码处,直到接到通知才继续执行或是中断。

         执行wait()方法前:线程必须先获取对象锁,否则会抛出异常IllegalMonitorStateException。

         执行wait()方法后:线程释放对象锁。

         因此wait()方法要写在同步方法或是同步代码块中。

         notify()方法同样是Object类的方法,它的作用是唤醒正在等待(wait状态)的线程(随机唤醒一个等待线程),需要注意的是,当前执行notify()的方法的线程执行完notify()方法后不会马上释放对象锁,因此被唤醒的等待线程也不会马上获取该对象锁,只有当执行notify()方法的线程执行完所在的同步代码块或是同步方法后,才会释放对象锁。

单个线程等待--单个线程唤醒(注意释放锁的时机)

public class TestThreadObject {

    public void testWaitThread(Object obj){
        synchronized (obj){

            try {
                System.out.println("开始执行wait()方法");
                obj.wait();
                System.out.println("结束执行wait()方法");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void testNofityThread(Object obj){
        synchronized (obj){

            try {
                System.out.println("开始执行notify()方法");
                obj.notify();
                System.out.println("结束执行notify()方法");
                Thread.sleep(1000);
                System.out.println("注意注意,notify()方法执行完毕了,还在synchronized里面,但是我还没释放对象锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("再次注意注意,notify()方法执行完毕后,不在synchronized里面,你猜我有没有释放对象锁");
    }
}

public class ThreadTestWait extends Thread {

    private Object obj;

    public ThreadTestWait(Object obj){
        super();
        this.obj = obj;
    }

    @Override
    public void run(){
        TestThreadObject testThreadObject = new TestThreadObject();
        testThreadObject.testWaitThread(obj);
    }
}

public class ThreadTestNotify extends Thread {

    private Object obj;

    public ThreadTestNotify(Object obj){
        super();
        this.obj = obj;
    }

    @Override
    public void run(){
        TestThreadObject testThreadObject = new TestThreadObject();
        testThreadObject.testNofityThread(obj);
    }
}


public class Test1 {

    public static void main(String[] args){

        Object obj = new Object();

        ThreadTestA threadTestA = new ThreadTestA(obj);
        threadTestA.start();
        ThreadTestB threadTestB = new ThreadTestB(obj);
        threadTestB.start();
    }
}


通过代码可以看出notify()方法执行完成后并不会马上释放锁,只有在执行完同步代码块或是同步方法后才释放锁。

唤醒所有等待线程(notifyAll()方法) 

       如果使用notify()方法的话,每次只能唤醒一个等待线程,当需要唤醒所有等待线程的时候,可以使用notifyAll()方法,唤醒是随机的。ThreadTestWait,ThreadTestNotify类不做改动,调整TestThreadObject类的输出内容便于观察。


public class TestThreadObject {

    public void testWaitThread(Object obj){
        synchronized (obj){

            try {
                System.out.println("线程" + Thread.currentThread().getName() + ":" + "开始执行wait()方法");
                obj.wait();
                System.out.println("线程" + Thread.currentThread().getName() + ":" + "结束执行wait()方法");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void testNofityThread(Object obj){
        synchronized (obj){

            System.out.println("线程" + Thread.currentThread().getName() + ":" + "开始执行notifyAll()方法");
            obj.notifyAll();
            System.out.println("线程" + Thread.currentThread().getName() + ":" + "结束执行notifyAll()方法");
        }
    }
}
public class Test1 {

    public static void main(String[] args){

        Object obj = new Object();

        ThreadTestWait waitThread = null;
        for(int i = 0; i < 5; i++){
            waitThread = new ThreadTestWait(obj);
            waitThread.setName("waitThread-" + i);
            waitThread.start();
        }

        ThreadTestNotify notifyThread = new ThreadTestNotify(obj);
        notifyThread.setName("notifyThread");
        notifyThread.start();
    }
}

所有等待线程成功被唤醒。

注意:唤醒等待线程的时候可能会出现以下情况

唤醒过早,造成程序逻辑错误。


等待线程中的wait条件发生变化的时候也可能会造成逻辑错误。

         

下篇内容:wait/notify 经典实现 生产者/消费者模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值