首页 > 编程语言 >1.4. 线程状态转化及源码解读

1.4. 线程状态转化及源码解读

时间:2025-01-11 21:01:22浏览次数:3  
标签:1.4 name parent Thread 源码 线程 null target

2.init()

package ThreadPackage;

public class ThreadTest {
    public static void main(String[] args) {
        // 创建一个线程,显式调用Thread的构造函数
        Thread thread = new Thread(() -> {
            System.out.println("线程运行");
        }, "MyThread"); // 传入Runnable和线程名称

        // 启动线程
        thread.start();
    }
}

552 row:

 /**
     * Allocates a new {@code Thread} object. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, target, name)}.
     *
     * @param  target
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this thread's run method is invoked.
     *
     * @param  name
     *         the name of the new thread
     */
    public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
  • 这个构造方法的作用是分配一个新的 Thread 对象。

  • 这个构造方法的行为等同于调用另一个构造方法 Thread(ThreadGroup, Runnable, String),并将 ThreadGroup 参数设置为 null

    • ThreadGroup 是 Java 提供的一个类,用于将多个线程组织在一起。线程组可以看作是一个容器,里面包含了多个线程以及其他线程组(线程组可以嵌套)。通过线程组,你可以对一组线程进行统一的管理。
  • @param target:解释了 target 参数的作用。如果 target 不为 null,线程启动时会调用 targetrun() 方法;如果为 null,则调用线程自身的 run() 方法。

  • @param name:解释了 name 参数的作用,表示线程的名称。

    /**
     * Initializes a Thread with the current AccessControlContext.
     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
     */
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }
 /**
     * Initializes a Thread.
     *
     * @param g the Thread group
     * @param target the object whose run() method gets called
     * @param name the name of the new Thread
     * @param stackSize the desired stack size for the new thread, or
     *        zero to indicate that this parameter is to be ignored.
     // 新线程所需的堆栈大小,或 0 表示忽略此参数
     
     * @param acc the AccessControlContext to inherit, or
     *            AccessController.getContext() if null
     // 要继承的 AccessControlContext,如果为空,则为 AccessController.getContext()
     
     * @param inheritThreadLocals if {@code true}, inherit initial values for
     *            inheritable thread-locals from the constructing thread
     */
     // 如果 {@code true},则从构造线程继承可继承线程位置的初始值

    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

理解:

这段代码展示了 Thread 类的 init() 方法的实现细节,它是线程初始化的核心逻辑。为了更好地理解这些代码在做什么,我们可以将其分解为几个关键部分,并用形象的方式解释每个部分的作用。


1. init()** 方法的作用**

init() 方法是 Thread 类的一个私有方法,用于初始化线程对象的内部状态。它会设置线程的名称、线程组、优先级、是否为守护线程(daemon)、线程的上下文类加载器、继承的线程本地变量等。

这个方法是 Thread 类的构造方法的核心部分,所有的构造方法最终都会调用这个方法来完成线程的初始化。


2. 形象化理解:线程的初始化过程

可以将线程的初始化过程比喻为创建一个“工人”(线程)并将其分配到一个“部门”(线程组)中,同时为这个工人设置一些属性,比如名字、工作任务、权限、工具等。


3. 代码分解与解释

3.1 检查线程名称
if (name == null) {
    throw new NullPointerException("name cannot be null");
}
this.name = name;
  • 作用:确保线程的名称不为空。如果名称为 null,会抛出 NullPointerException
  • 形象化:每个工人(线程)都需要一个名字,名字不能为空。

3.2 获取当前线程和安全管理器
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
  • 作用
    • currentThread() 获取当前正在运行的线程(即创建这个新线程的线程)。
    • System.getSecurityManager() 获取当前的安全管理器(SecurityManager),用于检查线程的权限。
  • 形象化:当前线程是“主管”,它负责创建新的工人(线程)。安全管理器是“安全检查员”,负责检查新工人是否符合安全要求。

3.3 确定线程组
if (g == null) {
    if (security != null) {
        g = security.getThreadGroup();
    }
    if (g == null) {
        g = parent.getThreadGroup();
    }
}
  • 作用
    • 如果没有显式指定线程组(g == null),则:
      1. 如果有安全管理器,询问安全管理器应该使用哪个线程组。
      2. 如果安全管理器没有指定线程组,则使用当前线程的线程组。
  • 形象化:如果没有明确指定新工人(线程)属于哪个部门(线程组),就让安全检查员(安全管理器)决定;如果安全检查员也没有意见,就让主管(当前线程)决定。

3.4 检查线程组的访问权限
g.checkAccess();
  • 作用:检查当前线程是否有权限访问指定的线程组。
  • 形象化:确保新工人(线程)被分配到的部门(线程组)是合法的,主管(当前线程)有权限将工人分配到这个部门。

3.5 添加未启动的线程到线程组
g.addUnstarted();
  • 作用:将新线程标记为“未启动”状态,并将其添加到线程组中。
  • 形象化:将新工人(线程)登记到部门(线程组)的员工名单中,但还没有开始工作。

3.6 设置线程的属性
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
  • 作用
    • 设置线程所属的线程组。
    • 设置线程是否为守护线程(daemon),默认继承父线程的守护状态。
    • 设置线程的优先级,默认继承父线程的优先级。
  • 形象化:新工人(线程)继承了主管(当前线程)的一些属性,比如是否是“夜班工人”(守护线程)以及工作优先级。

3.7 设置上下文类加载器
if (security == null || isCCLOverridden(parent.getClass()))
    this.contextClassLoader = parent.getContextClassLoader();
else
    this.contextClassLoader = parent.contextClassLoader;
  • 作用:设置线程的上下文类加载器(contextClassLoader),用于加载线程运行时需要的类。
  • 形象化:为新工人(线程)分配一个工具箱(类加载器),工具箱的内容由主管(当前线程)决定。

3.8 设置继承的线程本地变量
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
    this.inheritableThreadLocals =
        ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
  • 作用:如果 inheritThreadLocalstrue,则从父线程继承线程本地变量(ThreadLocal)。
  • 形象化:新工人(线程)可以继承主管(当前线程)的一些私人工具(线程本地变量)。

3.9 设置线程的堆栈大小
this.stackSize = stackSize;
  • 作用:设置线程的堆栈大小。如果为 0,表示使用默认堆栈大小。
  • 形象化:为新工人(线程)分配工作空间的大小。

3.10 分配线程 ID
tid = nextThreadID();
  • 作用:为线程分配一个唯一的 ID。
  • 形象化:为新工人(线程)发放一个工号。

4. 总结:init()** 方法的整体流程**

  1. 检查线程名称是否为空。
  2. 获取当前线程和安全管理器。
  3. 确定线程所属的线程组。
  4. 检查线程组的访问权限。
  5. 将线程添加到线程组中。
  6. 设置线程的属性(名称、守护状态、优先级、类加载器等)。
  7. 继承父线程的线程本地变量(如果需要)。
  8. 设置线程的堆栈大小。
  9. 分配线程的唯一 ID。

5. 形象化总结

可以将 init() 方法比喻为“创建一个新工人并分配到部门”的过程:

  1. 给工人起一个名字。
  2. 确定工人属于哪个部门(线程组)。
  3. 检查工人是否符合安全要求。
  4. 将工人登记到部门的员工名单中。
  5. 为工人设置属性(是否夜班、优先级、工具箱等)。
  6. 如果需要,继承主管的一些私人工具。
  7. 分配工作空间和工号。

通过这个过程,线程对象就被完整地初始化了,准备好可以被启动(start())并执行任务了。

Runnable= 操作系统中的 Ready(就绪态) 和 Running(运行态)

标签:1.4,name,parent,Thread,源码,线程,null,target
From: https://blog.csdn.net/web2u/article/details/145082409

相关文章

  • 基于ssm四S店预约保养系统,附源码+数据库+论文+开题+任务书,包安装调试
    1、项目介绍基于ssm的四S店预约保养系统,分为用户、管理员用户-功能:登录、注册、个人中心、车辆信息管理、公告信息管理、预约保养管理管理员-功能:登录、首页、个人中心、管理员管理、车辆信息管理、基础数据管理、公告信息管理、用户管理、约保养管理2、技术框架运行系统:W......
  • 基于ssm学生资助管理系统,附源码+数据库+论文+开题+任务书+PPT,包安装调试
    1、项目介绍图4.1即为设计的管理员功能结构,管理员权限操作的功能包括审核学生的家庭经济信息,对家庭经济的证明文件进行下载查看,可以管理学生监护人信息,管理公告,管理资助名单信息以及管理学生信息等。图4.2即为设计的学生功能结构,学生权限操作的功能包括登记家庭经济信息,上......
  • 2025毕设springboot 大学生志愿者信息管理系统论文+源码
    系统程序文件列表开题报告内容研究背景在当今社会,志愿服务已成为大学生参与社会实践、提升自我价值的重要途径。随着大学生志愿者队伍的不断壮大,如何高效、有序地管理这一庞大群体,成为摆在高校和社会组织面前的一大挑战。传统的志愿者管理方式往往依赖于纸质记录和人工调度......
  • 2025毕设springboot 大学生志愿者服务管理微信小程序的设计与实现论文+源码
    系统程序文件列表开题报告内容研究背景随着社会的不断进步和志愿服务精神的广泛传播,大学生作为社会的一股重要力量,积极参与各类志愿服务活动,不仅有助于个人成长,还能为社会带来积极影响。然而,传统的志愿者服务管理方式往往存在信息更新不及时、报名流程繁琐、志愿服务时长记......
  • 05容器篇(D2_集合 - D6_容器源码分析篇 - D2_LinkedList)
    目录本章目标一、基本介绍二、原理分析1.数据结构2.默认容量&最大容量3.扩容机制4.为什么LinkedList查询慢,增删快?1>为什么增删快?2>为什么查询慢?三、经典大厂面试题1.ArrayList的JDK1.8之前与之后的实现区别?2.List和Map区别?3.Array和ArrayList有何......
  • 05容器篇(D2_集合 - D6_容器源码分析篇 - D3_HashMap)
    目录本章目标一、基本介绍1.什么是HashMap?2.HashMap类的继承关系二、原理分析1.哈希表2.存储数据过程1>存储过程中相关属性2>存储过程图解3>存储过程源码分析3.底层数据1>什么是数据结构?2>HashMap的数据结构3>数据结构的源码三、源码分析1.HashMa......
  • java香烟销售管理系统论文+源码 2025毕设
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着社会的发展,烟草行业在经济中占据着重要的地位。然而,传统的香烟销售管理方式面临着诸多挑战。在市场方面,消费者需求日益多样化,对香烟的种类、......
  • java智能排课系统的设计与实现论文+源码 2025毕设
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着教育规模的不断扩大和教育资源的日益丰富,传统的人工排课方式已经难以满足现代教育管理的需求。在学校中,课程种类繁多、教师数量众多、教学资......
  • Dreamweaver修改织梦网站源码全攻略:从基础操作到高级定制
    Dreamweaver是一款强大的可视化网页编辑工具,非常适合用来修改基于织梦CMS构建的网站源码。以下是几个实用技巧,帮助开发者更高效地完成这项任务:项目结构理解:熟悉织梦网站的整体目录结构,了解各个文件夹和文件的作用。特别是data、include、templets等关键路径下的内容,对于后续开发......
  • flask框架体育科技运动综合信息平台毕设源码+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景关于体育科技运动综合信息平台的研究,现有研究多侧重于体育管理的某一单独方面,如运动员管理或者赛事组织等部分内容。专门针对整合运动......