构造方法
thread的构造方法分成了两类,1类是我们平时使用的公开构造方法:
public Thread()
public Thread(Runnable target)
....
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
另外还有一个构造方法,是安卓添加的用于runtime调用,内部初始化调用的方法也和上面不同。我们暂时先不看,先分析一下平时创建线程对象的这个方法。
构造方法实现直接调用了init
init
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
//1.设置线程名
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
//2.设置线程的线程组,如果未指定,则此线程的线程组为当前初始化线程的线程组
Thread parent = currentThread();
...
if (g == null) {
//这里有一段注释说,安卓不支持SecurityManager,所以删除了相关代码
g = parent.getThreadGroup();
}
//所属线程组未启动线程计数+1
g.addUnstarted();
this.group = g;
//3.设置线程的其他属性
//线程是否是守护线程以及优先级都继承自当前线程
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
this.target = target;
//4.调用init2 执行剩余初始化操作
init2(parent);
//5.设置线程的堆栈大小。但是否生效要看虚拟机。那么在art虚拟机上是否生效呢,我们后续再说
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
//6.设置当前线程id
tid = nextThreadID();
}
init2
在上面的init方法中,只是设置了一些thread的基本属性,剩余的初始化操作放在了init2中。另外,我们开头说的另一种runtime调用的构造方法,也会调用init2方法进行初始化。
private void init2(Thread parent) {
this.contextClassLoader = parent.getContextClassLoader();//设置此线程的上下文类加载器
this.inheritedAccessControlContext = AccessController.getContext();//这里可以看到,我们在构造方法中设置的AccessController并没有用。至于这个AccessController是什么呢,我们先不关注
if (parent.inheritableThreadLocals != null) {
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(
parent.inheritableThreadLocals);//设置从双亲线程继承来的ThreadLocal
}
}
nextThreadID
private static long threadSeqNumber;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
静态变量累加后返回。
到这里为止,我们的thread就已经初始化完毕了。在过程中,基本没有调用什么native方法,也没有什么特殊操作,就是简单的对thread对象的属性复制,自然也没有真的创建出一个线程。
网友评论