Thread.join()简单介绍

Android  Java  2024年7月31日 pm6:38发布4个月前更新 城堡大人
139 0 0

前言

简单记录一下Thread.join()的作用。

这里只是简单记录一下,方便自己回顾而已。

正文

join()是在Thread.java中定义

join源码

/**
 * Waits for this thread to die.[等待这个线程死亡]
 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
public final void join() throws InterruptedException {
    join(0);
}

最终调用的是 join(long millis)

public final void join(long millis)
throws InterruptedException {
    synchronized(lock) {
    long base = System.currentTimeMillis();
    long now = 0;
    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }
    //如果传入0,就走这
    if (millis == 0) {
        //判断是否存活
        while (isAlive()) {
            //0时表示一直等待,直到notifyAll()或notify()通知
            lock.wait(0);
        }
    } else {
        while (isAlive()) {
            //倒计时
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            //等待指定的时间
            lock.wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
    }
}
  1. 如果传入值millis为0时,需要等待线程死亡(任务结束)才会释放。

  2. 如果传入值millis大于0时,要么倒计时结束主动释放,要么线程死亡(任务结束),满足其一即可退出。

demo测试

下面简单的测试一下。先定义一个线程,如下。

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "name : " + getName() + " start ");
        for (int i = 0; i < 5; i++) {
            try {
                Log.d(TAG, "name : " + getName() + " [ " + i + " ] ");
                sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        Log.d(TAG, "name : " + getName() + " end ");
    }
}
不使用join()
private void test() {
    MyThread myThreadA = new MyThread("Thread_A");
    myThreadA.start();
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " start ");
    for (int i = 0; i < 5; i++) {
        Log.d(TAG, "name : " + Thread.currentThread().getName() + " [ " + i + " ] ");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " end ");
}

在main()中执行test()方法。执行后打印结果如下:

name : main start 
name : Thread_A start 
name : main [ 0 ] 
name : Thread_A [ 0 ] 
name : main [ 1 ] 
name : Thread_A [ 1 ] 
name : main [ 2 ] 
name : Thread_A [ 2 ] 
name : main [ 3 ] 
name : Thread_A [ 3 ] 
name : main [ 4 ] 
name : Thread_A [ 4 ] 
name : main end 
name : Thread_A end 

main线程和Thread_A一起抢占CPU资源的。

使用join()

下面代码是在上面基础上添加了join()方法,如下:

private void test() {
    MyThread myThreadA = new MyThread("Thread_A");
    myThreadA.start();
    //添加join()开始
    try {
        myThreadA.join();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    //添加join()结束
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " start ");
    for (int i = 0; i < 5; i++) {
        Log.d(TAG, "name : " + Thread.currentThread().getName() + " [ " + i + " ] ");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " end ");
}

在main()中执行test()方法。执行后打印结果如下:

name : Thread_A start 
name : Thread_A [ 0 ] 
name : Thread_A [ 1 ] 
name : Thread_A [ 2 ] 
name : Thread_A [ 3 ] 
name : Thread_A [ 4 ] 
name : Thread_A end 
name : main start 
name : main [ 0 ] 
name : main [ 1 ] 
name : main [ 2 ] 
name : main [ 3 ] 
name : main [ 4 ] 
name : main end 

上面的打印顺序是有顺序了,都规规矩矩的。也就是CPU一直被Thread_A占用,main老老实实等着Thread_A死亡才可以抢CPU。

小结

  1. 调用join()的线程具有优先执行权。

  2. 当有线程调用join()后,其他线程会阻塞,直到调用join()线程死亡。

参考文章

  1. 《Java并发编程之美》

  2. 《Thread.java源码》

 历史上的今天

  1. 2023: init的启动(0条评论)
  2. 2022: [摘]Android输入法基于GooglePinyin开源代码进行修改(0条评论)
  3. 2021: 梁小斌:中国,我的钥匙丢了(0条评论)
  4. 2019: 叔本华:只有经过深思的东西才能成为真知(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

[摘]Android CircleImageView圆形头像图片

前言本文摘抄,记录于此,方便自己查阅而已。正文Android想要使用ImageView圆形头像图片,可以自己定义一个CircleImageView继承ImageView类,也可以使用Glide框架来加载ImageView圆形图片,下面分别来介绍这两种形式。方法一:定义CircleImage...

LayoutInflater之inflate()简单分析

前言简单记录一下Android中LayoutInflater中inflate()的使用以及源码的简单跟踪。记录于此,方便自己查阅。正文LayoutInflater初始化对于LayoutInflater,我们并不陌生,经常使用。//方法1LayoutInflater inflater...

嫣然若雪:余生,看淡所有,珍惜拥有

现实生活中,有太多的欲望,求不到,爱不得,为自己搭建了牢笼,囚禁在很深的执念里,得不到,放不下。人生本就不易,生活里本就有太多的苦,烦恼不捡自然无,要捡天天有,没有谁能把日子过得一直顺遂。有些人,因为自己的执念,让生活增添不必要的负担;有些人,因为一点小事,让自己活得心烦意乱。人生的痛苦都是自...

JobIntentService的使用

前言简单记录一下JobIntentService的使用,后面高版本又废弃了,推荐使用Android Jetpack了。虽然废弃了,但还是记录一下(之前没记录)。水文一篇,哈哈,大佬们可以跳过。正文Android 8.0对系统资源的管控更加严格,添加了后台限制规则。如果满足以下任意条件...

再见,老何

屋子里灯光照耀,屋子外烟雾缭绕。烟灰最终承受不住自身的重量掉落下来。整个夏夜像被人按上了静音键,只有无声的等待。我在屋里,父亲在屋外。日子被日历一页页撕开,而今天是最后一页。我像往常一样追赶着太阳去学校,仿佛我们就代表着初升的朝阳。阳光透过树叶小心翼翼的洒在课桌上,连它都看出来了分别的气息,笔尖划...

BiuTextView替代TextView

前言Android 高版本后,TextView走马灯耗CPU。使用BiuTextView替代TextView来实现跑马灯。注意,下面测试还要其他应用使用surfaceflinger,所以很高,我们只是对比同一环境下,BiuTextView和TextView跑马灯的情况。正文说明:D...