第二章:深入理解Thread构造函数

it2025-02-17  4

线程的命名

线程的默认命名:

Thread()Thread(Runnable target)Thread(ThreadGroup group,Runnable target)

如果没有为线程显示地指定一个名字,那么线程会以“Thread-”作为前缀与一个自增数字进行组合,这个自增数字在整个JVM进程中会不断自增。

关于修改线程名:

public final synchronized void setName(String name) { checkAccess(); if (name == null) { throw new NullPointerException("name cannot be null"); } this.name = name; if (threadStatus != 0) { setNativeName(name); } }

线程不是NEW状态,对其的修改将不会生效。

线程的父子关系

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();

一个线程的创建肯定是由另一个线程完成。

被创建线程的父线程一定是创建它的线程。

Thread与ThreadGroup

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(); } }

如果在构造Thread的时候没有显式地指定一个ThreadGroup,那么子线程将会被加入到父线程所在的线程组,并且和父线程同一个优先级。

main线程所在的ThreadGroup称为main。

Thread与JVM虚拟机栈

stacksize越大代表着正在线程内方法调用递归的深度就越深,statcksize越小则代表着创建的线程数量越多。

JVM内存结构

1.程序计数器:

程序计数器在JVM中所起的作用就是存放当前线程接下来将要执行的字节码指令、分支、循环、跳转、异常处理等。在任何时候,一个处理器值执行其中的一个线程指令,为了能够在CPU时间片轮转切换上下文之后顺利回到正确的执行位置,每条线程都需要独立的计数器,个线程之间互不影响,因此JVM将此块内存区域设计成了线程私有的。

2.JAVA虚拟机栈:

java虚拟机栈也是线程私有的,它的生命周期与线程相同,是在JVM运行时创建的。在线程中,方法在执行的时候都会创建一个名为栈帧的数据结构。一般将栈帧内存的大小称为宽度,栈帧的数量则称为虚拟机栈的深度。

3.本地方法栈:

JVM为本地方法所划分的内存区域,而且它是线程私有的。

4.堆内存:

堆内存是JVM中最大的一块内存区域,被所有线程共享。

5.方法区:

方法区也是被多个线程所共享的内存区域,它主要用于储存已被虚拟机加载的类信息、常量、静态变量、即时编译器(JIT)编译后的代码等数据。(堆内存的一个逻辑区域)

Thread与虚拟机栈

栈内存划分的大小将直接决定在一个JVM进程中可以创建多少个线程。

java进程的粗略大小=堆内存+线程数量*栈内存

线程数量=(最大地址空间 - JVM堆内存 - ReservedOsMemory)/ThreadStackSize

守护线程

守护线程具备自动结束生命周期的特性。

若JVM中没有一个非守护线程,则JVM的进程会退出。 守护线程一般用于处理一些后台操作。

父线程是守护线程,子线程也会是守护线程。反之亦然。

设置守护线程:

在启动前调用setDaemon()方法才能生效。如果一个线程已经死亡,那么再设置会抛出IllegalThreadStateException。

使用守护线程:

希望当关闭某些线程的时候(可以是JVM),同时自动关闭一些线程。

最新回复(0)