线程交互

线程交互的基础知识

首先看下java.lang.Object的类的三个方法:

  • void notify()
    唤醒此对象监视器上等待的单个线程(随机唤醒一个)
  • void notifyAll()
    唤醒此对象监视器上等待的所有线程
  • void wait()
    使当前线程进入等待,直到其他线程调用此对象的notify()方法或notifyAll()方法

例如:线程A中,调用了obj.wait()方法,线程A就会停止执行,转为等待状态,直到其他线程调用了obj.notify()方法。obj对象成为了多个线程之间的有效通信手段。
注意:对于等待和通知,必须从同步环境中调用wait()、
notify()、notifyAll()方法,也就是他们必须包含在对应的synchronized语句中。必须拥有此对象的锁。

例子

线程ThreadB用于计算1-100的和

/**
 * @Time : 2019/04/04 下午 02:34
 * @Author : xiuc_shi
 **/
public class ThreadB extends Thread {
    public int total = 0;
    public void run(){
        synchronized (this){
            for(int i = 0;i <= 100;i++)
                total += i;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ThreadA

/**
 * @Time : 2019/04/04 下午 02:35
 * @Author : xiuc_shi
 **/
public class ThreadA {
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        System.out.println("等待对象b完成计算。。。");
        System.out.println("b对象计算的总和是:" + b.total);
    }
}

输出结果是:
等待对象b完成计算。。。
b对象计算的总和是:0

线程B并没有计算完成线程A就输出了b.total,导致错误,所以我们可以使用wait()方法让A等待B计算完成,再通知A线程继续执行。
线程A调用wait()方法的synchronized语句获得的锁必须是线程B的实例,因为线程B中的求和同步代码块需要的就是自己的实例锁,他们等待的是同一个锁对象。
wait()执行后,当前线程就会放弃锁,其他线程获得该锁,而notify()方法执行后却不一定马上释放锁,因为可能同步代码块还有代码没执行完。
ThreadA

public static void main(String[] args){
    ThreadB b = new ThreadB();
    b.start();
    synchronized (b){
        try {
            b.wait();//线程A进入等待状态
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println("等待对象b完成计算。。。");
    System.out.println("b对象计算的总和是:" + b.total);
}

ThreadB

public void run(){
    synchronized (this){
        for(int i = 0;i <= 100;i++)
            total += i;
        this.notify();//唤醒线程A继续执行
    }
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

wait()和notify()的工作流程

线程A在调用wait()前会获得锁对象的监视器,执行wait()方法后会释放锁对象的监视器,线程B在调用notify()前也必须获得对象监视器,notify()方法执行后尝试唤醒一个等待线程,这里是线程A,线程A被唤醒后不会马上去执行后续代码,而是先获得锁对象的监视器。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容