zoukankan      html  css  js  c++  java
  • 我也学习JAVA多线程-join

    【原文链接】:https://blog.tecchen.tech ,博文同步发布到博客园。
    由于精力有限,对文章的更新可能不能及时同步,请点击上面的原文链接访问最新内容。
    欢迎访问我的个人网站:https://www.tecchen.tech

    在工作中,挺少遇到join关键字,但很多多线程资料和面试过程中,初中级开发工程师总会遇到join。
    今天一起学习下join。
    join的作用:等待指定的时间(当为0时,一直等待),直到这个线程执行结束。
    先看join方法的定义,join是java.lang.Thread的一个普通方法。

    package java.lang;
    
    // Thread竟然实现了Runnable接口,之前好像注意到过,但是没在意。
    // 根据构造方法和run()方法可以看出,本质还是执行的Runnable的实现。
    public class Thread implements Runnable {
        …
        public final void join() throws InterruptedException {
            join(0);
        }
        …
    }
    

    演示代码

    public class ThreadLearnJoin {
    
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "睡觉");
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "起床");
                }
            }, "sub-thread");
            t.start();
    
            System.out.println(Thread.currentThread().getName() + "线程join前");
            t.join();
            System.out.println(Thread.currentThread().getName() + "线程join后");
        }
    }
    

    执行结果

    main线程join前
    sub-thread睡觉
    sub-thread起床
    main线程join后
    

    源码分析

    继续分析join(0)的代码,首先需要注意的是synchronized关键字,其次是isAlive()和wait(0)。在演示代码中,主线程调用名称为sub-thread的子线程t的join()方法。
    主线程先获取t对象上的锁,并且当t为Alive状态时,继续调用t的wait(0)方法。
    由于wait()方法是Object的方法,跟子线程t并没有关系,wait()会释放t对象上的锁,并阻塞当前main线程。
    这里也就隐藏了一个点:t线程调用start()后,进入执行状态,运行run()方法中的代码,和t对象上的锁并没有任何关系。
    run方法并没有进入synchronized的同步区。

    public final synchronized void join(long millis) throws InterruptedException {
        …
        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        }
        …
    }
    

    参考资料

    问题:虽然s.join()被调用的地方是发生在“Father主线程”中,但是s.join()是通过“子线程s”去调用的join()。  
    那么,join()方法中的isAlive()应该是判断“子线程s”是不是Alive状态;对应的wait(0)也应该是“让子线程s”等待才对。
    但如果是这样的话,s.join()的作用怎么可能是“让主线程等待,直到子线程s完成为止”呢,应该是让"子线程等待才对(因为调用子线程对象s的wait方法嘛)"?  
    答案:wait()的作用是让“当前线程”等待,而这里的“当前线程”是指当前在CPU上运行的线程。所以,虽然是调用子线程的wait()方法,但是它是通过“主线程”去调用的;
    所以,休眠的是主线程,而不是“子线程”!
    
    这个这么讲的不清楚吧?
    调用wait()方法 应该是当前线程持有的对象调用wait() 让线程等,并释放对象锁。
    在主线程中调用了s.join() join()方法用synchronized修饰了,也就是说当前主线程已经持有了s的锁 这个调用s这个对象wait()方法 让主线程等待并释放s对象锁。
    
  • 相关阅读:
    Unity攻击敌人时产生泛白效果
    将网页发布到远程windows server
    IIS服务器添加网站
    ASP.NET添加Mysql数据源
    ASP.NET网页VS利用文件系统发布
    爱的印记
    生如夏花之绚烂,死如秋叶之静美
    WordPress函数小结
    设置WordPress文章关键词自动获取,文章所属分类名称,描述自动获取文章内容,给文章的图片自动加上AlT标签
    童年的流逝
  • 原文地址:https://www.cnblogs.com/Candies/p/10635419.html
Copyright © 2011-2022 走看看