java的三大特性之一,继承;那线程之间是否有继承关系?看一下thread的源码。
1 /**
2 * Initializes a Thread.
3 *
4 * @param g the Thread group
5 * @param target the object whose run() method gets called
6 * @param name the name of the new Thread
7 * @param stackSize the desired stack size for the new thread, or
8 * zero to indicate that this parameter is to be ignored.
9 * @param acc the AccessControlContext to inherit, or
10 * AccessController.getContext() if null
11 * @param inheritThreadLocals if {@code true}, inherit initial values for
12 * inheritable thread-locals from the constructing thread
13 */
14 private void init(ThreadGroup g, Runnable target, String name,
15 long stackSize, AccessControlContext acc,
16 boolean inheritThreadLocals) {
17 if (name == null) {
18 throw new NullPointerException("name cannot be null");
19 }
20
21 this.name = name;
22
23 Thread parent = currentThread();
24 SecurityManager security = System.getSecurityManager();
25 if (g == null) {
26 /* Determine if it‘s an applet or not */
27
28 /* If there is a security manager, ask the security manager
29 what to do. */
30 if (security != null) {
31 g = security.getThreadGroup();
32 }
33
34 /* If the security doesn‘t have a strong opinion of the matter
35 use the parent thread group. */
36 if (g == null) {
37 g = parent.getThreadGroup();
38 }
39 }
40
41 /* checkAccess regardless of whether or not threadgroup is
42 explicitly passed in. */
43 g.checkAccess();
44
45 /*
46 * Do we have the required permissions?
47 */
48 if (security != null) {
49 if (isCCLOverridden(getClass())) {
50 security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
51 }
52 }
53
54 g.addUnstarted();
55
56 this.group = g;
57 this.daemon = parent.isDaemon();
58 this.priority = parent.getPriority();
59 if (security == null || isCCLOverridden(parent.getClass()))
60 this.contextClassLoader = parent.getContextClassLoader();
61 else
62 this.contextClassLoader = parent.contextClassLoader;
63 this.inheritedAccessControlContext =
64 acc != null ? acc : AccessController.getContext();
65 this.target = target;
66 setPriority(priority);
67 if (inheritThreadLocals && parent.inheritableThreadLocals != null)
68 this.inheritableThreadLocals =
69 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
70 /* Stash the specified stack size in case the VM cares */
71 this.stackSize = stackSize;
72
73 /* Set thread ID */
74 tid = nextThreadID();
75 }
纵观thread的所有构造函数中,都调用了init方法,不难从中发现线程之间的父子关系。
if (name == null) {
throw new NullPointerException("name cannot be null");
}
name:即线程的名称,可以自定义,默认采用Thread-+数字给线程命名。
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
在线程的生命周期中,如果一个线程new出来之后,在start之前,只是一个thread实例,并没有创建一个新的线程,所以这里的 Thread parent = currentThread(); 代表的是创建它的那个线程。
因此可以得出结论:
1.一个线程一定是由另一个线程创建的。
2.被创建的线程的父线程 是创建它的线程。
3.main函数所在的线程是由jvm创建的,因此推断出所有的线程的父线程是main线程。
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();
}
}
init方法中,第一个参数为 ThreadGroup,从上面的代码块看出,如果没有传入线程组,则默认加入父线程所在的线程组。下面代码测试一下:
public static void main(String[] args) {
Thread t1 = new Thread("t1");
ThreadGroup group = new ThreadGroup("group1");
Thread t2 = new Thread(group, "t2");
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("父线程组 name:"+threadGroup.getName());
System.out.println("t1所在线程组 name:"+t1.getThreadGroup().getName());
System.out.println("t2所在线程组 name:"+t2.getThreadGroup().getName());
}
结果:
父线程组 name:main
t1所在线程组 name:main
t2所在线程组 name:group1
这里我们先创建线程t1,线程组group1,线程t2,在创建t2的时候,将group1做为参数传递到线程t2的创建中,而t1并没有指定线程组。
分别获取当前线程的线程组name,t1的线程组name,t2的线程组name,可见t1因为没有指定线程组,被加到了当前线程的线程组中。
原文:https://www.cnblogs.com/fengyue0520/p/10423516.html