美文网首页
Thread的.start()与.run()的区别

Thread的.start()与.run()的区别

作者: 白花蛇草可乐 | 来源:发表于2019-09-28 16:16 被阅读0次

1、Thread的.start()与.run()的区别

start()

start()方法启动线程,真正实现了多线程运行,无需等待方法体代码执行完毕就可以直接继续执行下面的代码。

严格来说,start()后线程进入就绪状态(ready),进入可运行线程池;之后获得CPU时间成为了运行中状态(running)。

java中将就绪和运行中状态统称为运行(RUNNABLE)。

run()

run()方法将线程体当作普通方法的方式调用,程序依然是要顺序执行。

run方法体执行完毕后才可继续执行下面的代码(实际上程序中依然只有主线程这一个线程)。

2、试验1

public class Try {

    public static void main(String... args) {

        Runnable runTask = () -> {
            try {
                System.out.println("sleeping...");
                Thread.sleep(5000);
                System.out.println("awake");
            } catch (InterruptedException e) {
                System.out.println("睡觉时被打");
            }
        };

        Thread thread1 = new Thread(runTask);
        Thread thread2 = new Thread(runTask);
        Thread thread3 = new Thread(runTask);

        thread1.start();
        thread2.start();
        thread3.start();

    }

}

运行结果:
sleeping...
sleeping...
sleeping...
awake
awake
awake

可以看到使用start()方法时三个线程一起启动,睡5秒后一起结束。

将最后的执行部分替换成run(),再来看一下结果

        thread1.run();
        thread2.run();
        thread3.run();
        
运行结果:
sleeping...
awake
sleeping...
awake
sleeping...
awake

三个线程按顺序先后执行,总计耗时15s

3、试验2

这个例子是为了说明,start启动的线程,确确实实是线程自己在跑,跟main()已经没关系了。

public class Try {

    public static void main(String... args) throws InterruptedException {

        Runnable runTask = () -> {
            try {
                System.out.println(Thread.currentThread().getName()
                        + " - " + Thread.currentThread().getState());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("睡觉时被打");
            }
        };

        Thread thread = new Thread(runTask);
        thread.setName("小张");

        System.out.println(thread.getName() + " - " + thread.getState());

        thread.start();

        // 这是为了确保线程真的跑完,查看到正确的状态
        Thread.sleep(2000);
        System.out.println(thread.getName() + " - " + thread.getState());

    }

}


运行结果:

小张 - NEW
小张 - RUNNABLE
小张 - TERMINATED

  1. new Thread()以后,打印出线程处于初始状态(NEW)

    (实现Runnable接口或者继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态)

  2. start()方法使线程变为运行状态(RUNNABLE)

  3. 等待2秒后,线程确实结束,此时状态为终止(TERMINATED)

接下来仍然将start()替换为run()看一下结果:

        Thread thread = new Thread(runTask);
        thread.setName("小张");

        System.out.println(thread.getName() + " - " + thread.getState());

        thread.run();

        // 这是为了确保线程真的跑完,查看到正确的状态
        Thread.sleep(2000);
        System.out.println(thread.getName() + " - " + thread.getState());
        
运行结果:
小张 - NEW
main - RUNNABLE
小张 - NEW
  1. new Thread()以后,小张处于初始状态(NEW)

  2. run()方法被调用后,实际的处理是main()线程自己跑的,main变成了运行状态(RUNNABLE)——即使调用的语句是thread.run(),而不是诸如main.run()

  3. main将调用部分运行完毕以后,小张仍然处于初始状态(NEW),没有任何变化

4、稍微深入一点来分析这件事情

Thread类中,start()方法调用的是一个native方法start0(),启动一个线程,最终在线程里执行目标对象的run()方法;

而直接使用run()方法的话,我们来看一下run()的代码:

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

其中的target,是在new Thread(runTask)时,通过构造器传入的,就是runTask这个实例自身。

所以直接调用线程的run方法,就相当于调用普通方法一样,由上往下执行。

相关文章

网友评论

      本文标题:Thread的.start()与.run()的区别

      本文链接:https://www.haomeiwen.com/subject/dectuctx.html