start()方法和run()方法区别与多线程抢占式运行原理

🎈个人公众号:🎈 :✨✨ 可为编程 ✨✨ 🍟🍟
🔑个人信条:🔑 知足知不足 有为有不为 为与不为皆为可为🌵
🍉本篇简介:🍉 本片详细说明了start()方法和run()方法区别与多线程抢占式运行原理和注意要点,并给出具体操作实例,如有出入还望指正。

关注公众号【可为编程】回复【面试】领取最新面试题!!!

start()与run()方法区别

在这里插入图片描述

我们通过一个例子来进行总结,我们写一个利用Thread创建的简单的多线程例子,然后分别执行start()与run()方法,执行结果如下所示:

/**
 * @author :zjc
 * @ProjectName: execises
 * @Package: com.execises.zjc.controller.thread
 * @ClassName: ThreadRunAndStartMethodCompare
 * @date :Created in 2021/7/17 10:20
 * @description:对比run()和start()方法
 * @modified By:
 * @version: v1.0.0$
 */
public class ThreadRunAndStartMethodCompare extends Thread {
    private String name;

    public ThreadRunAndStartMethodCompare(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        super.run();
        System.out.println(name);
    }

    public static void main(String[] args) {
        new ThreadRunAndStartMethodCompare("唐山大兄本兄").run();
        //new ThreadRunAndStartMethodCompare("唐山大兄本兄").start();

    }

}

关注公众号【可为编程】回复【面试】领取最新面试题!!!
这里先执行了start()方法
在这里插入图片描述
在执行时,我们看到新生成了一个线程,这样与主线程分离开,实现了并行执行。
start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码:
关注公众号【可为编程】回复【面试】领取最新面试题!!!

1、通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。
2、然后通过此Thread类调用方法run()来完成其运行操作,这里方法run()称为线程体,它包含了要执行的这个线程的内容。
3、run()方法运行结束,此线程终止,而CPU再运行其它线程。

执行run方法
在这里插入图片描述

run()方法在这里可以看到并没有线程产生,只有单独的主进程

只是当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。在这里我们是直接用run()方法,这只是调用一个方法而已,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。

Thread底层也是用Runnable的run()方法来执行,其中target就是Runnable的变量名。

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

Thread对象的run()方法在一种循环下,使线程一直运行,直到不满足条件为止,在你的main()里创建并运行了一些线程,调用Thread类的start()方法将为线程执行特殊的初始化的过程,来配置线程,然后由线程执行机制调用run()方法。如果你不调用start()方法,线程就不会启动。
关注公众号【可为编程】回复【面试】领取最新面试题!!!
因为线程调度机制的行为是不确定的,所以每次运行该程序都会有不同的结果,你可以把你的循环次数增多些,然后看看执行的结果,你会发现main()的主线程和Thread子线程是交替运行的。我们看下面一段代码:

/**
 * @author :zjc
 * @ProjectName: execises
 * @Package: com.execises.zjc.controller.thread
 * @ClassName: ThreadOpByThread
 * @date :Created in 2021/7/16 15:03
 * @description:创建多线程之继承Thread类
 * @modified By:
 * @version: v1.0.0$
 */
public class ThreadOpByThread extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + i);
        }
    }

    static class testThread {
        public static void main(String[] args) {
            ThreadOpByThread threadOpByThread = new ThreadOpByThread();
            threadOpByThread.start();
            for (int i = 0; i < 100; i++) {
                System.out.println("我是主线程"+ i);
            }

        }
    }

}

输出结果为:

我是主线程0
Thread-00
我是主线程1
Thread-01
Thread-02
Thread-03
Thread-04
Thread-05
我是主线程2
我是主线程3
我是主线程4
我是主线程5
我是主线程6
我是主线程7
我是主线程8
Thread-06

在执行过程中会相互并发穿插执行,子线程执行完毕后依然会回到主线程,交给主线程最终执行,这也就是并发执行的高效率之所在。

多线程抢占式运行原理

经过我运行下面这段代码,发现每次生成的线程顺序号都是会变的,并不是按照顺序来执行:

/**
 * @author :zjc
 * @ProjectName: execises
 * @Package: com.execises.zjc.controller.thread
 * @ClassName: ThreadRunAndStartMethodCompare
 * @date :Created in 2021/7/17 10:20
 * @description:对比run()和start()方法
 * @modified By:
 * @version: v1.0.0$
 */
public class ThreadRunAndStartMethodCompare extends Thread {
    private String name;

    public ThreadRunAndStartMethodCompare(String name) {
        this.name = name;
    }
    public ThreadRunAndStartMethodCompare() {
    }

    @Override
    public void run() {
        super.run();
        System.out.println(name);
    }

    public static void main(String[] args) {
        ThreadRunAndStartMethodCompare threadRunAndStartMethodCompare = new ThreadRunAndStartMethodCompare();
        //new ThreadRunAndStartMethodCompare("张建超").run();
        for (int i = 0; i < 100; i++) {
            threadRunAndStartMethodCompare.demo(i);
        }
    }
    public void demo(int i) {
        synchronized (this) {
            new ThreadRunAndStartMethodCompare("唐山大兄本兄" + i).start();
        }
    }

}

输出结果:
关注公众号【可为编程】回复【面试】领取最新面试题!!!

唐山大兄本兄0
唐山大兄本兄5
唐山大兄本兄3
唐山大兄本兄2
唐山大兄本兄1
唐山大兄本兄4
唐山大兄本兄6
唐山大兄本兄7
唐山大兄本兄8
唐山大兄本兄10
唐山大兄本兄18
唐山大兄本兄12
唐山大兄本兄20
唐山大兄本兄13
唐山大兄本兄14

在这里插入图片描述
原因:

1、当java虚拟机(也就是经常说的 JVM)执行mian方法的时候,他会找操作系统(也就是os)开辟一条main方法通向cpu的路径,这个路径就是main线程,也就是所说的主线程。

2、接着cpu通过这个线程,也就是这个路径,就可以执行main方法了。

3、当我们new了一个Thread对象,这个时候又开辟了一条通向cpu的路径,而这条路径是用来执行run方法的。
关注公众号【可为编程】回复【面试】领取最新面试题!!!
4、而现在对于cpu而言,他就有了很多条执行的路径,cpu就有了选择的权利,cpu他喜欢谁,就会执行哪条路径,我们是控制不了cpu的,所有就有了出现随机打印的结果。

反过来说,两个线程,一个main线程,一个新线程,他们一起抢夺cpu的执行权(即 cpu的执行时间),谁抢到了,谁先执行。

也可以这么来理解:

0到99这段时间太短,对于CPU分配给这个线程的时间片来说足够完成了,也就呈现出0到99个线程同时初始化,然后剩下的线程再争夺CPU资源,在我们Debug调试的时候输出就是0到99的顺序,不用Debug调试直接运行就不是0到99输出。大致可以理解为创建了所有的线程,再争用资源。调试的时候有断点,产生了优先级,所以才按序输出的。

这边发现一个讲run()和start()的比较详细的文章,链接地址放在这里:
https://blog.csdn.net/chengp919/article/details/77336328

欢迎感兴趣的小伙伴一起探讨学习知识,以上是个人的一些总结分享,如有错误的地方望各位留言指出,十分感谢。觉得有用的话别忘点赞、收藏、关注,手留余香! 😗 😗 😗

这里是一个真诚的***青年技术交流QQ群:761374713***,不管你是大学生、社畜、想学习变成的其他人员,欢迎大家加入我们,一起成长,一起进步,真诚的欢迎你,不管是技术,还是人生,还是学习方法。有道无术,术亦可求,有术无道,止于术。在这里插入图片描述

欢迎大家关注【可为编程】,成长,进步,编程,技术、掌握更多知识!
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

可为编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值