Thread类源码分析(1)

2021-01-14 15:45:32 浏览数 (1)

Thread类源码分析(1)

概述


1.Thread常见属性

2.Thread构造方法

3.Thread.start()

4.Thread.run()

第1节 Thread常见属性


我们以JDK 1.8为例,讲解Thread类的一些常见属性。首先分析一下Thread类的声明:

代码语言:javascript复制
public class Thread implements Runnable

从Thread类的声明可以看出,Thread类其实也是继承了Runnable接口,是Runnable接口的子类。Thread常见属性及其含义如下:

代码语言:javascript复制
/** ------ 1. Thread常用属性 ------ **/

//线程名字
private volatile String name;
//优先级
private int  priority;
//是否是守护线程
private boolean     daemon = false;
//将会被执行的Runnable.
private Runnable target;
//所属的线程组
private ThreadGroup group;
//当前线程的指定栈大小,如果线程的创建者不指定大小,那默认值就是0
//对这个数如何进行操作取决于JVM,有些JVM会忽略掉这个参数
private long stackSize;
//线程id
private long tid;
//用来生成thread ID
private static long threadSeqNumber;
//标识线程状态,默认是线程未启动
private int threadStatus = 0;
//得到下个thread ID
private static synchronized long nextThreadID() {
  return   threadSeqNumber;
}
//当前线程附属的ThreadLocal,而ThreadLocalMap会被ThreadLocal维护)
ThreadLocal.ThreadLocalMap threadLocals = null;
// 主要作用:为子线程提供从父线程那里继承的值
//在创建子线程时,子线程会接收所有可继承的线程局部变量的初始值,以获得父线程所具有的值
//如果一个子线程调用 InheritableThreadLocal 的 get() ,那么它将与它的父线程看到同一个对象
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
//为java.util.concurrent.locks.LockSupport.park提供的变量
volatile Object parkBlocker;
//阻塞器锁,主要用于处理阻塞情况
private volatile Interruptible blocker;
//阻断锁
private Object blockerLock = new Object();
//线程的最低优先级
public final static int MIN_PRIORITY = 1;
//线程的默认优先级
public final static int NORM_PRIORITY = 5;
//线程的最高的优先级
public final static int MAX_PRIORITY = 10;

第2节 Thread构造方法


Thread构造器有如下几种:

代码语言:javascript复制
/** Thread构造器 */

// 无参构造
public Thread() {
    init(null, null, "Thread-"   nextThreadNum(), 0);
}

// 用Runnable作为参数的构造器
public Thread(Runnable target) {
    init(null, target, "Thread-"   nextThreadNum(), 0);
}

Thread(Runnable target, AccessControlContext acc) {
    init(null, target, "Thread-"   nextThreadNum(), 0, acc, false);
}

public Thread(ThreadGroup group, Runnable target) {
    init(group, target, "Thread-"   nextThreadNum(), 0);
}

public Thread(String name) {
    init(null, null, name, 0);
}

public Thread(ThreadGroup group, String name) {
    init(group, null, name, 0);
}

public Thread(Runnable target, String name) {
    init(null, target, name, 0);
}

public Thread(ThreadGroup group, Runnable target, String name) {
    init(group, target, name, 0);
}

public Thread(ThreadGroup group, Runnable target, String name,
              long stackSize) {
    init(group, target, name, stackSize);
}

每个构造器都是调用的init()方法,重点分析init()方法。

代码语言:javascript复制
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();
    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();
        }
    }

    /* checkAccess regardless of whether or not threadgroup is
       explicitly passed in. */
    g.checkAccess();

    /*
     * Do we have the required permissions?
     */
    if (security != null) {
        if (isCCLOverridden(getClass())) {
            security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
        }
    }
    //记录线程组未启动线程个数
    g.addUnstarted();
    //线程组
    this.group = g;
   //是否守护线程
    this.daemon = parent.isDaemon();
   //优先级——父线程的优先级
    this.priority = parent.getPriority();
    if (security == null || isCCLOverridden(parent.getClass()))
        this.contextClassLoader = parent.getContextClassLoader();
    else
        this.contextClassLoader = parent.contextClassLoader;
    this.inheritedAccessControlContext =
            acc != null ? acc : AccessController.getContext();
    //线程执行体
    this.target = target;
    //设置优先级
    setPriority(priority);
    if (inheritThreadLocals && parent.inheritableThreadLocals != null)
       // 为子线程提供从父线程那里继承的值
        this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    /* 设置stackSize */
    this.stackSize = stackSize;

    /* 设置线程id */
    tid = nextThreadID();
}

第3节 Thread.start()


调用start()方法启动线程,执行线程的run方法。

代码语言:javascript复制
/**
 * 调用start()方法启动线程,执行线程的run方法
 * 此方法会导致当前调用start()方法的线程和新线程并发执行
 */
public synchronized void start() {
    /**
     * 线程状态校验,线程必须是0即新建态才能启动
     */
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    //通知线程组当前线程即将执行,同时线程组中未启动线程数-1
    group.add(this);

    boolean started = false;
    try {
    //使线程进入可执行(runnable状态)的状态
        start0();
        started = true;
    } finally {
        try {
            if (!started) {
          //启动失败后,修改线程组未启动线程数 1
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            /* do nothing. If start0 threw a Throwable then
              it will be passed up the call stack */
        }
    }
}

// start()实际上是通过本地方法start0()启动线程的。
// start0()会新运行一个线程,新线程会调用run()方法
private native void start0();

第4节 Thread.run()


线程执行的具体任务在run()方法中。

代码语言:javascript复制
/**
 * 线程执行的具体任务
 */
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

tatget就是Runnable对象——Thread类的run()方法会调用Runnable对象的run()方法。

0 人点赞