首页 > 编程语言 >JUC源码讲解:逐步解析 join()

JUC源码讲解:逐步解析 join()

时间:2024-03-13 20:34:51浏览次数:35  
标签:JUC join currentThread Thread 源码 线程 wait

JUC源码讲解:逐步解析 join()

问题抛出

join() 在源码中其实是使用了 wait() 方法的, 因此, wait() 的特性 join() 都能继承过来, 我们知道wait()有什么特性呢?

wait()的特性:

  • 会释放锁
  • 对中断异常敏感
  • 会释放CPU时间片

我也对wait()做了讲解,想了解可移步 https://www.cnblogs.com/acdongla/p/18071381

可是, join() 真的会释放锁吗? 为什么一些例子中, 使用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;
        }
    }
}

先看这段代码:

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

可以看到, 传递的时间不能是负数

一个重点来了, alive() 函数出现了:

if (millis == 0) {
    while (isAlive()) {
        wait(0);
    }

isAlive() 是对线程状态的检查, 必须是start()后的线程才会满足条件.

因此,因为有 isAlive() 的检查 , join()函数只能在线程 start() 后使用

注意!!! 这里的 wait(0)

我们知道, wait()能释放锁资源, 可我们需要注意一个问题, 这里的 wait() 释放的是谁的锁资源?

答: **释放的是当前线程的锁资源, 这里的wait()是 currentThread.wait(), 是 this.wait() **

我们写一段代码来说明这个问题

public class Main {

    @SneakyThrows
    public static void main(String[] args) {
        new Thread(new YYThread(), "YY-1").start();
        Thread.sleep(100);
        new Thread(new YYThread(), "YY-2").start();
    }

    static class YYThread implements Runnable {

        @SneakyThrows
        @Override
        public void run() {
            /// 注意!!! 这里使用锁对象是 Main.class
            synchronized (Main.clsss) {
                System.out.println(Thread.currentThread().getName() + "启动了");

                Thread.currentThread().join();

            }
        }
    }
}

注意, 在sync中使用的锁对象是 Main.class

运行这段代码,会发现线程 "YY-2" 被阻塞了

为什么, join()不是同wait()一样,会释放锁资源吗?

但!!! wait()释放的是当前线程的锁资源, 因此,使用全局变量来作为锁是不可行的

我们把run()函数做这样的修改,就可以不阻塞了

public void run() {
    /// 修改了锁, 修改为了当前线程
    synchronized (Thread.currentThread()) {
        System.out.println(Thread.currentThread().getName() + "启动了");

        Thread.currentThread().join();

    }
}

修改后,从输出上看,两个线程都正常运行了

总结

  • join() 完全继承了 wait() 方法的特性, 但需要注意的事, join() 中的源码使用了wait(), 代表的事 currentThread.wait(), 是"当前线程.wait()",因此释放的只是当前线程的锁资源
  • 因为源码中对isAlive() 的判断, join() 只能在线程 start() 之后才能使用
  • join() 的参数不能是负数

标签:JUC,join,currentThread,Thread,源码,线程,wait
From: https://www.cnblogs.com/acdongla/p/18071456

相关文章

  • 基于的校园商铺平台(源码+开题)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容基于校园商铺平台的研究背景、意义、目的及研究内容一、研究背景随着信息技术的飞速发展,互联网已经渗透到人们生活的方方面面,特别是在高校校园内,学生对于便......
  • 基于的校园商城(源码+开题)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的快速发展和互联网的普及,电子商务逐渐渗透到人们生活的方方面面。特别是在高校校园内,学生对于线上购物、便捷支付的需求日益增长。传统......
  • JUC源码讲解:wait()
    JUC源码讲解:wait()抛出问题在线程调用wait()时,是否会释放锁?线程的状态是什么样的?会对异常敏感吗?此时CPU资源是否会被释放呢?我们在源码中找找答案吧!分析源码进入wait()函数,可以看到这样一段代码:publicfinalvoidwait()throwsInterruptedException{wait(0);}......
  • JUC 源码讲解:sleep()
    JUC源码讲解:sleep()抛出问题sleep()能使线程进入TIMED_WAITING状态,那么,在使用sleep()会不会释放锁?被中断了会不会抛出异常?在线程使用sleep()时,CPU会不会被释放?我们在源码中和实战中看看答案吧!查看源码进入sleep()源码,可以看到它是一个native方法,但是注释很详细,让我们......
  • java毕设安卓基于Android的校园二手交易平台(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着移动互联网技术的飞速发展,智能手机已成为大学生生活中不可或缺的一部分。特别是在数字化校园建设的推动下,各类移动应用纷纷涌现,极大地便利了师生......
  • Java版企业电子招标采购系统源码—企业战略布局下的采购寻源
    功能模块:待办消息,招标公告,中标公告,信息发布描述:全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为外部供应商集中推送展示与其相关的所有采购业务信息(历史合作、考察整改,绩效评价等),支持供应商信......
  • 工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计
     鸿鹄工程项目管理系统SpringCloud+SpringBoot+Mybatis+Vue+ElementUI+前后端分离构建工程项目管理系统1.项目背景一、随着公司的快速发展,企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性,公司对内部工程管理的提升提出了更......
  • glibc 2.23 源码分析
    1.基础知识1.1Linux进程内存布局Linux系统在装载elf格式的程序文件时,会调用loader把可执行文件中的各个段依次载入到从某一地址开始的空间中(载入地址取决于linkeditor(ld)和机器地址位数,在32位机器上是0x8048000,即128M处)。以32位机器为例,首先被载入的是.text......
  • MYSQL- 使用SQL99 实现7种JOIN 操作
    DESCemployees; DESCdepartments;   ##中图就是内连接SELECTlast_name,department_nameFROMemployeeseJOINdepartmentsdONe.department_id=d.department_id##sql99内连接SELECTlast_name,department_name,cityFROMemployeeseINNERJOIN......
  • 基于Java+Vue+Mysql的门店管理系统(附配套文档和源码)【毕业设计分享】
          前言:门店管理系统是一个综合性的软件解决方案,旨在帮助门店高效地管理日常运营、提升服务质量、优化资源配置和增强决策能力。以下是您提到的各个管理模块的简要概述:门店管理:门店信息管理:记录门店的基本信息,如门店名称、地址、联系方式、营业时间等。门店布局管......