深入了解Thread构造函数-1

124 阅读2分钟

「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

前言

Java中的Thread为我们提供了很多构造函数,接下来学习一下这些构造函数以及其中一些可能之前未关注到的细节~

线程的命名

在构造线程的时候给线程起一个有特殊意义的名字会有助于问题的排查和线程的跟踪。

线程的默认命名

下面这几个构造函数,并没有提供为线程命名的参数,那么此时线程的命名是什么样的呢?

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

JDK中对应的源码是这样的:

public Thread(Runnable target){
    init(null,target,"Thread-" + nextThreadNum(),0);
}
/* For autonumbering anonymous threads.*/
private static int threadInitNumber;
private static synchronized int nextThreadNum(){
    return threadInitNumber++;
}

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

public static void main(String[] args){
    IntStream.range(0,5).boxed().map(
        i -> new Thread(
            () -> System.out.println(Thread.currentThread().getName())
        )
    ).forEach(Thread::start);
}

上述代码使用无参的构造函数创建了5个线程,并且分别输出了各自的名字,输出如下:
Thread-0
Thread-1
Thread-2
Thread-3
Thread-4

命名线程

下面来实战一下为线程赋予一个特殊的名字,Thread提供了这样的构造函数:

Thread(Runnable target,String name)
Thread(String name)
Thread(ThreadGroup group,Runnable target,String name)
Thread(ThreadGroup group,Runnable target,String name,long stackSize)
Thread(ThreadGroup group,String name)

比如我们给线程命名为以“Test-”为前缀,用0~4作为后缀,代码如下:

private final static String PREFIX = “Test-”;
public static void main(String[] args){
    IntStream.range(0,5).mapToObj(ThreadConstruction::createThread)
        .forEach(Thread::start);
}
public static Thread createThread(final int intName){
    return new Thread(
        () -> System.out.println(Thread.currentThread().getName())
            ,PREFIX + intName);
}

代码执行结果如下: Test-0
Test-1
Test-2
Test-3
Test-4

修改线程的名字

无论我们是使用默认的函数命名规则,还是指定一个特殊的名字,在线程启动之前还有一个机会对其进行修改(一旦线程启动,名字就不能再被修改),下面是Thread的setName源码:

public final synchronized void setName(String name){
    checkAccess();
    this.name - name.toCharArray();
    if(threadStatus != 0){
        //线程不是NEW状态,对其的修改将不会生效
        setNativeName(name);
    }
}