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

1、继承关系:

首先看到Thread类的声明:

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

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

2、构造函数:

找到其无参构造函数:

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

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

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
	return threadInitNumber++;
    }

可以看到threadInitNumber是类静态变量。且他的增加是线程安全的。(synchronized )

继续查看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代码初始化线程需要的系统资源。并同时调用run()方法。

可见,线程底层的实现是通过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接口实现的线程类需要这样启动的原因。

可见Thread类也是一个代理类。(他实现了代理模式)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java码界探秘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值