前言
一 结构关系
...... }
public interface Runnable { public abstract void run(); }
二 构造函数
public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0); } ......
/** * 很明显这个方法是用来初始化线程的 * @param g 线程组 你创建的线程最终会被添加到这个线程组中 * @param target Runnable类型 用于回调 * @param name 即将创建的线程的名字 * @param stackSize 即将创建的线程的栈的大小,如果是0,表明忽略此参数 */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { //调用native层的currentThread函数获取当前环境所在的线程,例如在Activity中,你获取的将是UI线程 Thread parent = currentThread(); if (g == null) { //线程parent所属的线程组 g = parent.getThreadGroup(); } //函数1 后台线程数加1 g.addUnstarted(); //保存线程组 this.group = g; //保存 Runnable类型 用于回调 this.target = target; //parent获取线程优先权1-10 this.priority = parent.getPriority(); //是否是后台线程 this.daemon = parent.isDaemon(); //设置线程的名字 setName(name); //函数2 init2(parent); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; //创建线程Id,线程的唯一标识 tid = nextThreadID(); }
1 addUnstarted
void addUnstarted() { synchronized(this) { if (destroyed) { throw new IllegalThreadStateException(); } nUnstartedThreads++; } }
/**
* Increments the count of unstarted threads in the thread group.
* Unstarted threads are not added to the thread group so that they
* can be collected if they are never started, but they must be
* counted so that daemon thread groups with unstarted threads in
* them are not destroyed.
*/
2 int2
private void init2(Thread parent) { //获取线程parent的类加载器 ClassLoader类型 this.contextClassLoader = parent.getContextClassLoader(); this.inheritedAccessControlContext = AccessController.getContext(); if (parent.inheritableThreadLocals != null) { //给当前线程创建ThreadLocalMap对象,并且继承parent的ThreadLocalMap中的数据 this.inheritableThreadLocals = ThreadLocal.createInheritedMap( parent.inheritableThreadLocals); } }
三 生命周期
1线程状态
public enum State { NEW,//被实例化之后,但还没有调用start启动 RUNNABLE,//调用了start函数之后就处于Runnable状态 BLOCKED,//调用join()、sleep()、wait()使线程处于Blocked状态 WAITING,// TIMED_WAITING,// TERMINATED;// }
(1) new
(2)Runnable
(4)Dead
2 线程的操作:
好,接下来借用网友一幅图加于说明:派生:线程在进程内派生出来,它即可由进程派生,也可由线程派生。阻塞(Block):如果一个线程在执行过程中需要等待某个事件发生,则被阻塞。激活(unblock):如果 阻塞 线程的事件发生,则该线程被激活并进入就绪 队列。调度(schedule):选择一个 就绪 线程进入执行 状态 。
四 函数分析
1 start函数分析
public synchronized void start() { /** *threadStatus ==0,说明该线程状态为"NEW",还没有启动过,一个线程只能启动一次,否则抛出异常。 */ if (threadStatus != 0) throw new IllegalThreadStateException(); /* 把当前线程添加到线程组中 */ group.add(this); started = false; try { //调用native层函数创建线程,native层的源码未找到先不讨论它 nativeCreate(this, stackSize, daemon); started = true; } finally { ...... } }
2 interrupt函数分析
public void interrupt() { if (this != Thread.currentThread()) checkAccess(); //blockerLock synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { nativeInterrupt(); b.interrupt(this); return; } }//调用native层函数完成线程中断 nativeInterrupt(); }
3 join函数分析
public final void join() throws InterruptedException { join(0); } public final void join(long millis) throws InterruptedException { synchronized(lock) { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { lock.wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } lock.wait(delay); now = System.currentTimeMillis() - base; } } } }
4 sleep与wait函数分析
public static void sleep(long millis) throws InterruptedException { Thread.sleep(millis, 0); }
public final void wait(long millis) throws InterruptedException { wait(millis, 0); }
5 常用函数总结
run():包含线程运行时所执行的代码
start():用于启动线程
sleep()、sleep(long millis):线程休眠,交出CPU,让CPU去执行其他的任务,然后线程进入阻塞状态,sleep方法不会释放锁
yield():使当前线程交出CPU,让CPU去执行其他的任务,但不会是线程进入阻塞状态,而是重置为就绪状态,yield方法不会释放锁
join()、join(long millis)、join(long millis,int nanoseconds):等待线程终止,直白的说 就是发起该子线程的线程 只有等待该子线程运行结束才能继续往下运行
wait():交出cpu,让CPU去执行其他的任务,让线程进入阻塞状态,同时也会释放锁
interrupt():中断线程,自stop函数过时之后,我们通过interrupt方法和isInterrupted()方法来停止正在运行的线程,注意只能中断已经处于阻塞的线程
getId():获取当前线程的ID
getName()、setName():获取和设置线程的名字
getPriority()、setPriority():获取和这是线程的优先级 一般property用1-10的整数表示,默认优先级是5,优先级最高是10,优先级高的线程被执行的机率高
setDaemon()、isDaemo():设置和判断是否是守护线程
currentThread():静态函数获取当前线程