1 源码解析
1.1构造方法
几个常用的变量
group:线程组 ,线程组包含其他的线程组,形成一个树结构,除了初始线程组外,其他的线程组都会有父线程,线程可以访问当前线程组的信息,不能访问父线程组信息
daemon:守护线程,
实际都是运行了init()方法,我们详细介绍下这方法
// ThreadGroup g, 线程组,创建的线程被加入到线程组 ,线程组是线程的集合,线程组组成了一个树,除了初始线程组,每个线程组都有一个parent线程组
// Runnable target,用于回调,Thread 的 run() 方法中会转掉该 target 的 run() 方法,这是线程真正处理事务的地方
//String name 线程名称
// stackSize 创建的线程的栈的大小,如果是0,表明忽略此参数
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
//调用native层的currentThread函数获取当前环境所在的线程,例如在Activity中,你获取的将是UI线程
Thread parent = currentThread();//native方法调用到了底层的代码
if (g == null) {
g = parent.getThreadGroup();
}
g.addUnstarted();//后台线程数加1
this.group = g;
this.target = target;
this.priority = parent.getPriority();
this.daemon = parent.isDaemon();
setName(name);
init2(parent);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
tid = nextThreadID();// //创建线程Id,线程的唯一标识
}
private void init2(Thread parent) {
//获取线程parent的类加载器 ClassLoader类型
this.contextClassLoader = parent.getContextClassLoader();
//设置ClassLoader成员变量
this.inheritedAccessControlContext = AccessController.getContext();//设置访问权限控制环境
if (parent.inheritableThreadLocals != null) {
//给当前线程创建ThreadLocalMap对象,并且继承parent的ThreadLocalMap中的数据
//创建Thread实例的ThreadLoacaleMap。需要用到父线程的ThreadLocaleMap,目的是为了将父线程中的变量副本拷贝一份到当前线程中。
//ThreadLocaleMap是一个Entry型的数组,Thread实例会将变量副本保存在这里面。
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(
parent.inheritableThreadLocals);
}
}
到这里Thread的初始化完成。
2 线程的生命周期,
1.New(线程创建未启动)
2.RUNNABLE(正在执行中的线程)
3.BLOCKED(被阻塞并且再等在监视器锁释放)调用join()、sleep()、wait()使线程处于Blocked状态
4.WAITING(等待被唤醒)
5.TIMED_WAITING(等待或睡眠一定时间被唤醒)
6.TERMINATED(线程终止,消亡)
1.new状态
new状态是新县城状态,通过new关键字实例化一个Thread对象就生产一个新线程,线程处于new状态的时候,仅仅是一个空线程们还没有分配系统资源,只能启动或者终止,线程调用new方法后,在start前处于新线程状态。
2.Runnable状态
Runnable也称为可运行状态,通过start方法的状态,线程获取了支持其运行的资源,并调度其run方法,这个状态不能想当然的认为是运行状态,因为这时的线程并不总是一直占用处理机,它也有可能不在运行,这是因为还有优先级和调度问题。
3.NOT Runnable状态
NOT Runnable也称为阻塞状态,当以下事件发生时,线程处于该状态:
a:调用supped、sleep方法
b:调用wait方法等待条件变量
c:线程处于I/O请求的等待
4.Dead也称为死亡状态,
run方法运行完毕、其他线程调用该线程的stop方法、异常终止都会使线程处理该状态
3关键方法
3.1 run()方法
处理线程中执行的逻辑,如果继承Thread类则必须重写该方法.
3.2 start()方法
//方法是加了锁的。
//原因是避免开发者在其它线程调用同一个Thread实例的这个方法,从而尽量避免抛出异常。
//这个方法之所以能够执行我们传入的Runnable里的run()方法,
//是应为JVM调用了Thread实例的run()方法。
public synchronized void start() {
//检查线程状态是否为0,为0表示是一个新状态,即还没被start()过。不为0就抛出异常。
//就是说,我们一个Thread实例,我们只能调用一次start()方法。
if (threadStatus != 0 || started)
throw new IllegalThreadStateException();
从这里开始才真正的线程加入到ThreadGroup组里。
//再重复一次,前面只是把nUnstartedThreads这个计数器进行了增量,并没有添加线程。
//同时,当线程启动了之后,nUnstartedThreads计数器会-1。因为就绪状态的线程少了一条啊!
group.add(this);
started = false;
try {
//Native方法。这里交由JVM处理,会调用Thread实例的run()方法。
nativeCreate(this, stackSize, daemon);
started = true;
} finally {
try {
if (!started) {
//如果没有被启动成功,Thread将会被移除ThreadGroup,
//同时,nUnstartedThreads计数器又增量1了
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
3.3 setPriority()方法
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
// Android-changed: Improve exception message when the new priority
// is out of bounds.
throw new IllegalArgumentException("Priority out of range: " + newPriority);
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
synchronized(this) {
this.priority = newPriority;
if (isAlive()) {
nativeSetPriority(newPriority);
}
}
}
}
// nativeSetPriority() 才是真正的给执行线程设置优先级, 所以如果不调用 setPriority() 方法, 创建 Thread 对象的时候, 其实压根就没有把线程设置优先级, 只是给 Thread 对象设置变量.
3.4 interrupt()方法
public void interrupt() {
//中断其他线程,需要先判断当前线程是否允许修改其他线程
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
nativeInterrupt();//nativa方法 终端线程
b.interrupt(this);
return;
}
}
nativeInterrupt();
}
Interruptible是神马我没看到。
join方法
- 线程安全,
- wait(0)方法,表示释放锁,线程进入等待状态