美文网首页
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