资讯专栏INFORMATION COLUMN

java中thread的join方法为什么能让线程插队

oysun / 1940人阅读

摘要:接收到之后,会再次进行判断,死亡之后,就跳出循环,方法结束,之后就继续执行主线程中的其他代码。同时我们也能看到方法里面能传递时间参数,大概作用就是等待指定时间之后,如果之前线程还未执行完成,那么久不再等待。

在面试中经常会遇到这样的问题:在主线程中有两个子线程,如果能让着两个子线程能顺序的执行?
答案自然是用join来使得两个线程顺序执行,先看一下具体代码

public class ThreadOfJoin {

    public static void main(String[] args) throws Exception {
        MyThread luck = new MyThread("Luck");
        MyThread timi = new MyThread("Timi");

        luck.start();
        luck.join();
        timi.start();
    }

    @Data
    static class MyThread extends Thread {
        private String userName;
        public MyThread(String userName) {
            this.userName = userName;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 5; i++) {
                    System.out.println(userName + " - " + i);
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

每个线程启动后,打印五次信息,通过不同的名字来区分是哪个线程打印的。执行结果如下

Luck - 0
Luck - 1
Luck - 2
Luck - 3
Luck - 4
Timi - 0
Timi - 1
Timi - 2
Timi - 3
Timi - 4

通过结果可以看到join可以使得两个线程是顺序执行,那为什么join能控制线程顺序执行呢,我们看下join的具体实现

//外部调用的方法
public final void join() throws InterruptedException {
    join(0);
}
//内部的具体实现
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通过synchronized关键字来保证线程安全,主线程在调用了luck.start()之后调用了luck.join(),当luck线程未执行完成是,主线程会被以下代码阻塞

if (millis == 0) {//join()方法默认milis为0
    while (isAlive()) {//线程未执行完成,此条件为true
        wait(0);//等待notify
    }
}

当luck线程执行完成之后,此线程的生命周期即将结束,在生命周期结束前,luck线程会使用notifyAll()方法,通知所有正在等待该对象锁的线程(我即将死去,你们不要再等了)。wait(0)接收到notify之后,会再次进行isAlive()判断,luck死亡之后,就跳出循环,join方法结束,之后就继续执行主线程中的其他代码。

同时我们也能看到join方法里面能传递时间参数,大概作用就是等待指定时间之后,如果之前线程还未执行完成,那么久不再等待。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77653.html

相关文章

  • java并发编程学习之CountDownLatch

    摘要:作用等待其他线程执行完后,在执行某个线程。可以多个线程插队到线程,线程等多个线程结束后才执行类似后面的,而可以等待多个线程执行完才执行,灵活性比更大。示例执行结果如下虽然线程休眠了秒,但是依然等到线程输出后,才输出。 作用 等待其他线程执行完后,在执行某个线程。类似之前的join,但是比join更强大。join可以多个线程插队到A线程,A线程等多个线程结束后才执行(类似后面的Cycli...

    antz 评论0 收藏0
  • java高并发之从零到放弃(二)

    摘要:可以用代替可以用代替定义的对象的值是不可变的今天就先到这里,大家可以看看这些内容的拓展记得点关注看更新,谢谢阅读 前言 java高并发第二篇讲的是java线程的基础依旧不多说废话 线程和进程 进程是操作系统运行的基础,是一个程序运行的实体,windows上打开任务管理器就能看到进程线程是轻量级的进程,是程序执行的最小单位,是在进程这个容器下进行的 线程基本操作 新建一个线程类有两种方式...

    cloud 评论0 收藏0
  • 一文读懂Java线程状态转换

    摘要:前言本文描述线程线程状态及状态转换,不会涉及过多理论,主要以代码示例说明线程状态如何转换。被终止线程执行完毕正常结束或执行过程中因未捕获异常意外终止都会是线程进入被终止状态。线程执行完毕打印状态。 前言 本文描述Java线程线程状态及状态转换,不会涉及过多理论,主要以代码示例说明线程状态如何转换。 基础知识 1. 线程状态 线程可以有6种状态: New(新建) Runnable(可运...

    summerpxy 评论0 收藏0
  • Java 重入锁 ReentrantLock 原理分析

    摘要:的主要功能和关键字一致,均是用于多线程的同步。而仅支持通过查询当前线程是否持有锁。由于和使用的是同一把可重入锁,所以线程可以进入方法,并再次获得锁,而不会被阻塞住。公平与非公平公平与非公平指的是线程获取锁的方式。 1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似。所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻...

    lx1036 评论0 收藏0
  • Java线程并发编程面试笔录一览

    摘要:创建线程的方式方式一将类声明为的子类。将该线程标记为守护线程或用户线程。其中方法隐含的线程为父线程。恢复线程,已过时。等待该线程销毁终止。更多的使当前线程在锁存器倒计数至零之前一直等待,除非线 知识体系图: showImg(https://segmentfault.com/img/bVbef6v?w=1280&h=960); 1、线程是什么? 线程是进程中独立运行的子任务。 2、创建线...

    bitkylin 评论0 收藏0

发表评论

0条评论

oysun

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<