Thread类中run和start的区别

一.认识 Thread类 中的 start() 和 run()

首先来看一张jdk-api中对于start 和 run 的描述.

 

二.方法的区别

 下面我们简单看一下代码:

// 继承Thread类 重写run()
class MyThread extends Thread {
    @Override
    public void run() {
        while (true) {
            System.out.println("thread");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo1 {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();

        while (true) {
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
// 通过重写Runnable 来实现创建线程
class MyRunnable implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo2 {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread();
        thread.start();


        while (true) {
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

通过上述代码, 我们可以看出, 无论哪一种方法创建线程, 我们都需要重写run(), 而API中对于run() 的介绍,如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。Thread 的子类应该重写该方法。run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

我们确定一件事, start() 才是真正启动线程的方法, 真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。

通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行, 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容Run方法运行结束, 此线程终止。然后CPU再调度其它线程。 一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止

三.运行结果的区别

图一, 继承Thread类打印效果

这个时候创建了新的线程, 打印了 thread

然后, 操作系统, 调度线程的时候, 是一个 "随机" 的过程

执行 sleep, 线程就进入阻塞.

sleep 时间一到, 线程就恢复就绪状态, 参与线程调度.

当两个线程都参与调度的时候, 不确定谁先谁后

 图二, 重写Runnable接口

这个时候只是打印了 main , 并没有创建新的线程

实现Runnable接口,创建Thread时,会调用

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

private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
        init(g, target, name, stackSize, null, true);
}

把Runnable的实现类赋值给target,当使用run方法时```java会调用我们实现时写的run()方法. 因此,run方法只是调用了一个普通方法,并没有启动另一个线程,程序还是会按照顺序执行相应的代码, 因此,无论使用哪种方式创建线程, run方法都是用来处理线程对应的业务逻辑. 

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

即将秃头的菜鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值