并发编程(六)java Thread.start()源码解读

1线程开启

我们先来看一下源码

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)
        throw new IllegalThreadStateException();

    /* Notify the group that this thread is about to be started
     * so that it can be added to the group's list of threads
     * and the group's unstarted count can be decremented. */
    group.add(this);

    boolean started = false;
    try {
        start0();
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            /* do nothing. If start0 threw a Throwable then
              it will be passed up the call stack */
        }
    }
}
复制代码

2源码解读

首先我们来看方法体public synchronized void start(),其中用了synchronize关键字修饰,代表此方法有锁,并且锁对象是当前调用的对象,并且避免多线程同时启动一个线程。

if (threadStatus != 0)
    throw new IllegalThreadStateException();
复制代码

如果这个线程不是初始状态就直接抛出非法线程状态异常,什么情况下会出现这种情况呢,比如一个需要执行一段时间的线程在很短的时间内连续start()方法调用了两次就会抛出异常。

并且我们可以点击看到threadStatus这个变量的定义:private volatile int threadStatus = 0;是volatile关键字修饰的,说明这个变量具有可见性和禁止指令重排序,能及时发现这个变量被其他线程改变,所以这里使用volatile关键字是非常有必要的。

group.add(this);
复制代码

上一章中我们遇到的是g.addUnstarted()线程组调用未开始的线程使未开始线程数量+1。这次是添加进线程组里,并使线程组里的线程+1,未开始线程数量-1。

boolean started = false;
    try {
        start0();
        started = true;
    } finally {
    try {
        if (!started) {
            group.threadStartFailed(this);
        }
    } catch (Throwable ignore) {
        /* do nothing. If start0 threw a Throwable then
          it will be passed up the call stack */
    }
}
复制代码

这里started是一个标志状态,设置初始状态为false,然后进行本地方法start0()的调用,如果成功开启,则设置started状态为true。 完全执行完之前,线程处于 Ready,完成后,只要cpu分配执行权,我们的线程就进入了Running状态。

如果starte0()方法出现异常,则在线程组中调用threadStartFailed(this)方法,这个方法里有一个remove,就是把我们线程组中记录的这个线程删除,并线程数-1,未开始线程数量+1。

并且threadStartFailed里有synchronize代码块,防止并发修改问题,所以修改数量不会出现问题。

为什么catch里什么都没有写呢?

Start0 这个异常,会直接反馈给我们的调用线程。 如果这个线程是在main线程,那么就会走Main函数里边的 thread.start方法抛出异常,然后main函数抛出异常。如果catch中进行处理, 我们的 thread.start方法感知不到异常,导致程序的错误的继续执行。

3最后总结

线程对象在初始化完成之后,调用start()方法就可以启动这个线程。线程start()方法的含义是:当前线程(即parent线程)同步告知Java虚拟机,只要线程规划器空闲,应立即启动调用start()方法的线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值