1、线程的命名#
在构造现成的时候可以为线程起一个名字。但是我们如果不给线程起名字,那线程会有一个怎样的命名呢?
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
如果没有为线程起名字,那么线程将会以“Thread-”作为前缀与一个自增数字进行组合,这个自增数字在整个JVM进程中将会不断自增

0
实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);
需要注意的是,不论你使用的是默认的命名还是特殊的名字,在线程启动之后还有一个机会可以对其进行修改,一旦线程启动,名字将不再被修改,下面是setName源码
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);
}
}
2、线程的父子关系#
Thread的所有构造函数,最终都会调用一个init,我们截取代码片段对其分析,不难发现新创建的任何一个线程都会有一个父线程:
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();
}
上面的代码中的currentThread()是获取当前线程,在线程的生命周期中,线程的最初状态为NEW,没有执行start方法之前,他只能算是一个Thread的实例,并不意味着一个新的线程被创建,因此currentThread()代表的将会是创建它的那个线程,因此我们可以得出以下结论:
- 一个线程的创建肯定是由另一个线程完成的
- 被创建线程的父线程是创建它的线程
我们都知道main函数所在的线程是由JVM创建的,也就是main线程,那就意味着我们前面创建的所有线程,其父线程都是main线程。