美文网首页
线程交互

线程交互

作者: topshi | 来源:发表于2019-04-15 14:19 被阅读0次

    线程交互的基础知识

    首先看下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被唤醒后不会马上去执行后续代码,而是先获得锁对象的监视器。

    相关文章

      网友评论

          本文标题:线程交互

          本文链接:https://www.haomeiwen.com/subject/voeuwqtx.html