• 43 线程的 run() 和 start() 有什么区别?


    线程的 run() 和 start() 有什么区别?

    答:

    • 调用 start() 方法是用来启动线程的,轮到该线程执行时,会自动调用 run();直接调用 run() 方法,无法达到启动多线程的目的,相当于主线程线性执行 Thread 对象的 run() 方法。

    • 一个线程对线的 start() 方法只能调用一次,多次调用会抛出 java.lang.IllegalThreadStateException 异常;run() 方法没有限制。
       

    原文链接: https://blog.csdn.net/meism5/article/details/90240272 (上文)
    原文链接: https://blog.csdn.net/woshizisezise/article/details/79938915 (下文)
     

    thread线程有5种状态,创建-就绪-运行-阻塞-死亡这五种,那么我们的start方法呢就是就绪这一步,因为这个时候我们的线程并没有立即的执行,而是得等待,等到我们的cpu有空闲的时候,才会执行线程里面的run方法,等run方法执行完了,线程就结束了。

    那么我们直接使用thread执行run方法会咋样呢?因为run方法是thread里面的一个普通的方法,所以我们直接调用run方法,这个时候它是会运行在我们的主线程中的,因为这个时候我们的程序中只有主线程一个线程,所以如果有两个线程,都是直接调用的run方法,那么他们的执行顺序一定是顺序执行,所以这样并没有做到多线程的这种目的。

    下面来写一段简单的代码,运行一下看看效果,加深大家的印象。

    public class ThreadDemo {
        public static void main(String[] args){
            Thread thread1 = new Thread(new MyRunnable());
            Thread thread2 = new Thread(new MyRunnable());
            thread1.start();
            thread2.start();
        }
    }
    
    class MyRunnable implements Runnable {
    
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println(i);
                    Thread.sleep(100);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

     

    根据我们上面的分析,这两个线程都是使用start方法开启的,所以并不需要等待另一个完成,所以他们的执行顺序应该是并行的,我们运行看一下结果:


     

    和我们分析的一样,那么我们改改代码,执行使用run方法,看看是否顺序执行:

     public static void main(String[] args){
        Thread thread1 = new Thread(new MyRunnable());
        Thread thread2 = new Thread(new MyRunnable());
        thread1.run();
        thread2.run();
    }
    

     


     

    其实这也很容易理解对不对,直接使用对象调用方法,那必须是这个方法执行完了代码才能往下走啊,嗯,没毛病!
     


     

    深入一点,我们来看看源码是怎么干的吧!

    首先看看run方法是如何做的,点击run方法会跳进Thread.java源码中:

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

     

    好理解吧?target不为空,就执行run方法,target是啥?

    /* What will be run. */
    private Runnable target;
    

     

    可以看到target就是我们的Runnable 对象本身,所以能理解吧,没毛病哈?

    下面来看看start方法如何干的!

    public synchronized void start() {
        //这里private volatile int threadStatus = 0;初始化的时候就是0
        //如果这里不为0的话就抛异常
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
    
        //把当前线程加入到线程组中
        //private ThreadGroup group;就是这么个东西
        group.add(this);
    
        //初始化标记位未启动
        boolean started = false;
        try {
            start0();
            //标识为启动状态
            started = true;
        } finally {
            try {
                //如果没开启,标识为启动失败
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
    
            }
        }
    }
    

     

    注意这里有个start0()方法,源码是

    private native void start0();
    

     

    这里用到了native修饰符,表示调用本机的操作系统函数,也可能是VM的,这是因为多线程需要我们机器底层的支持,比如说cpu啥的。

  • 相关阅读:
    h5实现 微信的授权登录
    js判断浏览器的环境(pc端,移动端,还是微信浏览器)
    动态判断时间插件显示到年月日时分秒
    H5发起微信支付
    Vue项目结合vux使用
    Swift学习笔记一:常量和变量
    iOS开发之解决系统数字键盘无文字时delete键无法监听的技巧
    Swift3.0之获取设备识别号deviceNo和保存账户AccountId
    Swift3.0之自定义debug阶段控制台打印
    Xcode之command+/快捷键添加注释不起作用
  • 原文地址:https://www.cnblogs.com/ynzj123/p/12820603.html
Copyright © 2020-2023  润新知