Java源码分析 – Thread线程类源码分析

发布于 2011-10-23 | 更新于 2020-09-20

1、继承关系:

首先看到Thread类的声明:

class Thread implements Runnable {
/* Make sure registerNatives is the first thing does. */

可知,其实现了Runnable接口,而Runnable接口有一个run()方法,所以Thread也实现了该方法。

2、构造函数:

找到其无参构造函数:

public Thread() {
init(null, null, “Thread-” + nextThreadNum(), 0);
}

这里的第三个参数是设置线程的名称,从下面的代码中可以看出,生成名称的规则是:”Thread-”加上创建的线程的个数(第几个)。

继续查看init方法:

private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
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();
this.name = name.toCharArray();
if (security == null || isCCLOverridden(parent.getClass()))
    this.contextClassLoader = parent.getContextClassLoader();
else
    this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext = AccessController.getContext();
this.target = target;
setPriority(priority);
    if (parent.inheritableThreadLocals != null)
    this.inheritableThreadLocals =
    ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    /* Stash the specified stack size in case the VM cares */
    this.stackSize = stackSize;

    /* Set thread ID */
    tid = nextThreadID();

    this.me = this;
}

初始化时设置了是否为守护线程,优先级,初始化名称。

3、Thread的start方法的实现:

public synchronized void start() {
/**
* This method is not invoked for the main method thread or “system”
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state “NEW”.
*/
if (threadStatus != 0 || this != me)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}

这里主要的是start0方法;查看其实现:

private native void start0();

这里使用了本地调用,通过C代码初始化线程需要的系统资源。

可见,线程底层的实现是通过C代码去完成的。

4、Thead的run方法的实现:

public void run() {
if (target != null) {
target.run();
}
}

这里的target实际上要保存的是一个Runnable接口的实现的引用:

private Runnable target;

所以使用继承Thread创建线程类时,需要重写run方法,因为默认的run方法什么也不干。

而当我们使用Runnable接口实现线程类时,为了启动线程,需要先勇该线程类实例初始化一个Thread,实际上就执行了如下构造函数:

public Thread(Runnable target) {
init(null, target, “Thread-” + nextThreadNum(), 0);
}

即是把线程类的引用保存到target中。这样,当调用Thread的run方法时,target就不为空了,而是继续调用了target的run方法,所以我们需要实现Runnable的run方法。这样通过Thread的run方法就调用到了Runnable实现类中的run方法。

这也是Runnable接口实现的线程类需要这样启动的原因。

本文作者: arthinking

本文链接: https://www.itzhai.comjava-source-code-analysis-thread-thread-class-source-code-analysis.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。

请帅旋喝一杯咖啡

咖啡=电量,给帅旋充杯咖啡,他会满电写代码!

IT宅

关注公众号及时获取网站内容更新。