Thread 的join方法解释

Thread 的join方法解释  一、作用  Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。具体看代码:  publicclassJoinTest{publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadJoinTestt1=newTh…

大家好,又见面了,我是你们的朋友全栈君。

  一、作用

  Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。具体看代码:

  

复制代码
public class JoinTest {
    public static void main(String [] args) throws InterruptedException {
        ThreadJoinTest t1 = new ThreadJoinTest("小明");
        ThreadJoinTest t2 = new ThreadJoinTest("小东");
        t1.start();
        /**join的意思是使得放弃当前线程的执行,并返回对应的线程,例如下面代码的意思就是:
         程序在main线程中调用t1线程的join方法,则main线程放弃cpu控制权,并返回t1线程继续执行直到线程t1执行完毕
         所以结果是t1线程执行完后,才到主线程执行,相当于在main线程中同步t1线程,t1执行完了,main线程才有执行的机会
         */
        t1.join();
        t2.start();
    }

}
class ThreadJoinTest extends Thread{
    public ThreadJoinTest(String name){
        super(name);
    }
    @Override
    public void run(){
        for(int i=0;i<1000;i++){
            System.out.println(this.getName() + ":" + i);
        }
    }
}
复制代码

上面程序结果是先打印完小明线程,在打印小东线程;  

上面注释也大概说明了join方法的作用:在A线程中调用了B线程的join()方法时,表示只有当B线程执行完毕时,A线程才能继续执行。注意,这里调用的join方法是没有传参的,join方法其实也可以传递一个参数给它的,具体看下面的简单例子:

复制代码
public class JoinTest {
    public static void main(String [] args) throws InterruptedException {
        ThreadJoinTest t1 = new ThreadJoinTest("小明");
        ThreadJoinTest t2 = new ThreadJoinTest("小东");
        t1.start();
        /**join方法可以传递参数,join(10)表示main线程会等待t1线程10毫秒,10毫秒过去后,
         * main线程和t1线程之间执行顺序由串行执行变为普通的并行执行
         */
        t1.join(10);
        t2.start();
    }

}
class ThreadJoinTest extends Thread{
    public ThreadJoinTest(String name){
        super(name);
    }
    @Override
    public void run(){
        for(int i=0;i<1000;i++){
            System.out.println(this.getName() + ":" + i);
        }
    }
}
复制代码

上面代码结果是:程序执行前面10毫秒内打印的都是小明线程,10毫秒后,小明和小东程序交替打印。

所以,join方法中如果传入参数,则表示这样的意思:如果A线程中掉用B线程的join(10),则表示A线程会等待B线程执行10毫秒,10毫秒过后,A、B线程并行执行。需要注意的是,jdk规定,join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕,即join(0)等价于join()。

  

  二、join与start调用顺序问题

  上面的讨论大概知道了join的作用了,那么,入股 join在start前调用,会出现什么后果呢?先看下面的测试结果

复制代码
public class JoinTest {
    public static void main(String [] args) throws InterruptedException {
        ThreadJoinTest t1 = new ThreadJoinTest("小明");
        ThreadJoinTest t2 = new ThreadJoinTest("小东");
        /**join方法可以在start方法前调用时,并不能起到同步的作用
         */
        t1.join();
        t1.start();
        //Thread.yield();
        t2.start();
    }

}
class ThreadJoinTest extends Thread{
    public ThreadJoinTest(String name){
        super(name);
    }
    @Override
    public void run(){
        for(int i=0;i<1000;i++){
            System.out.println(this.getName() + ":" + i);
        }
    }
}
复制代码

上面代码执行结果是:小明和小东线程交替打印。

所以得到以下结论:join方法必须在线程start方法调用之后调用才有意义。这个也很容易理解:如果一个线程都没有start,那它也就无法同步了。

 

  三、join方法实现原理

  有了上面的例子,我们大概知道join方法的作用了,那么,join方法实现的原理是什么呢?

  其实,join方法是通过调用线程的wait方法来达到同步的目的的。例如,A线程中调用了B线程的join方法,则相当于A线程调用了B线程的wait方法,在调用了B线程的wait方法后,A线程就会进入阻塞状态,具体看下面的源码:

复制代码
public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
复制代码

从源码中可以看到:join方法的原理就是调用相应线程的wait方法进行等待操作的,例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll方法唤醒A线程,从而达到同步的目的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133259.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Java 最常见的 200+ 面试题:面试必备「建议收藏」

    这份面试清单是从我2015年做了TeamLeader之后开始收集的,一方面是给公司招聘用,另一方面是想用它来挖掘在Java技术栈中,还有那些知识点是我不知道的,我想找到这些技术盲点,然后修复它,以此来提高自己的技术水平。虽然我是从2009年就开始参加编程工作了,但我依旧觉得自己现在要学的东西很多,并且学习这些知识,让我很有成就感和满足感,那所以何乐而不为呢?说回面试的事,这份面试…

  • Linux 修改文件权限

    Linux 修改文件权限目录:1、介绍:2、权限说明3、用户4、权限设置5、权限设置格式:(1)增加权限:(2)撤销权限(3)无任何权限1、介绍:​ Linux系统中,每个文件或目录都有访问许可权限,用它来确定以何种方式对文件或目录进行访问和操作。在Linux中,如果要对文件的权限进行修改,那么可在终端中使用chmod命令对其文件的权限进行修改,但是chmod命令修改文件权限有两种方式:1、字母法,2、数字法2、权限说明​ (1)只读:表示只允许读取内容,而禁止其对该文件做其他任何操作​ 字母法:‘r’

  • Linuxstat_linux内核编译的基本流程

    Linuxstat_linux内核编译的基本流程stat函数讲解:表头文件:#include#include定义函数:intstat(constchar*file_name,structstat*buf);函数说明:通过文件名filename获取文件信息,并保存在buf所指的结构体stat中返回值:执行成功则返回0,失败返回-1,错误代码存于errno错误代码:ENOENT参数file_name指定的文件不存在ENOT…

  • pytest fixtures_premier fixture

    pytest fixtures_premier fixturefixture的优势Pytest的fixture相对于传统的xUnit的setup/teardown函数做了显著的改进:命名方式灵活,不局限于setup和teardown这几个命名conf

  • jvm内存模型、jvm内存结构、Java内存结构、Java内存模型(JMM)、Java对象模型的区别(吐血研究整理)

    jvm内存模型、jvm内存结构、Java内存结构、Java内存模型(JMM)、Java对象模型的区别(吐血研究整理)jvm内存模型:JVM内存模型则是指JVM的内存分区。jvm内存结构:等同于Java内存结构,汉语虽然博大精深,但是也经常会因为命名很雷同让人懵逼或者混淆不清。Java内存结构:Java内存模型(JMM):java内存模型又称为JMM。为了解决Java多线程对共享数据的读写一致性问题,通过Happens-Before语义(延伸出了as-if-serial)定义了Java程序对数据的访问规则,修正之前由于读写冲突导致的Cache数据不一致的问题。具体到HotspotVM的实现..

  • group by 和 order by 的区别 + 理解过程

    group by 和 order by 的区别 + 理解过程orderby和groupby的区别order by 和 group by 的区别:1,order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。2,group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。注意:聚合函数是—sum()、count()、…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号