如何正确的启动线程(内含源码解析和高频面试题)

1、启动线程的正确和错误方式

结论:使用start方法启动线程

1.1 start()和run()的比较

/**
 * start方法和run方法
 */
public class StartAndRunMethod {
    public static void main (String[] args) {
        Runnable runnable = ()->{
            System.out.println(Thread.currentThread().getName());
        };
        runnable.run();

        new Thread(runnable).start();
    }
}

输出:

main
Thread-0

是不是和我们想的不太一样

不建议使用直接调用的方式执行run方法,这样违背了我们创建线程的初衷。

1.2start方法的解读

1.2.1 start方法含义

  1. 启动新线程(通知JVM在空闲的情况下,启动新线程)

    • 调用start方法的顺序并不能决定最后线程的执行顺序(执行顺序是要看JVM的状态和各种其他的因素)
    • 会让两个线程同时运行。我们需要一个线程来执行start语句(通常是main线程),另一个线程就是start语句创建的新线程
  2. 新的线程要进行一系列的准备工作才能工作。

    • 首先是自己处于就绪状态(自己已经获取到了除CPU以外的其他资源)
    • 做完上叙工作之后,我们线程才能被JVM或OS调度到执行状态,调度到执行状态之后我们才能获得到CPU资源
    • 然后才能调度到执行状态,执行方法内容
  3. 不可以重复调用start方法

    Thread thread = new Thread();
    thread.start();
    thread.start();
    

    此时抛出异常:IllegalThreadStateException非法的线程状态

    • 一旦start,线程就会变化各种状态,一旦线程执行完毕,就会进入终止状态(该状态永远不可以变化了)所以我们再一次的start就会报错(可以结合后面的源码学习)

1.3 start源码解析

  1. 启动新线程检查线程状态
  2. 加入线程组
  3. 调用start0()
public synchronized void start() {
    /* 判断状态是否正确 */
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    /* 加入线程组*/
    group.add(this);

    boolean started = false;
    try {
        start0();//调用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 */
        }
    }
}

private native void start0();

关于native方法(该方法不是使用Java写的,而是使用C++写的)主要是调用OS的方法

1.4 常见面试题

一个线程两次调用start方法会出现什么情况?why

分析start源码,在最开始的时候就会进行状态的判断,如果前面已经执行了start方法,就会报错(非法的线程状态)

在面试的时候要提到线程的状态,最开始是什么状态,然后是什么状态(不要问什么就答什么,一定要给知识点引申一下,往自己知道的知识点引)

既然start方法会调用run方法,为什么我们选择调用start方法,而不是直接调用run方法

只有使用了start方法,才是创建一个新线程。否则就是使用旧线程来执行run方法(比如说是main线程)

慕课网悟空老师课程笔记 https://coding.imooc.com/class/362.html
谢谢大家看到这里,如有不对的地方请在评论区指正

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值