关于Thread的start和run方法的执行方式

今天突然想到,在主线程中启动一个子线程,在子线程执行完毕后,是否可以自动销毁的疑惑,带着问题,开始考虑编码,在编码过程中分别使用了Runnable和Thead两种不同的方式,下面先看第一中Runnable方式。

  1. Runnable方式
class RunnableTest implements Runnable {

    @Override
    public void run() {
        System.out.println("我是新启动的Runnable!");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在该方式中,先让子线程休眠2秒中(用于在主线程中持续观察当前所有线程的变化情况),主线程调用如下:

public class ThreadDemo {
    public static void main(String[] arg) throws InterruptedException {
        RunnableTest().run();
        while (true){
            Thread[] threads = findAllThreads();
            for(Thread t : threads){
                System.out.println(t.getId()+":"+t.getName());
            }
            Thread.sleep(1000);
        }
    }

    /**
     * 用于获取当前JVM中所有的线程
     * @return
     */
    public static Thread[] findAllThreads() {
        ThreadGroup group = Thread.currentThread().getThreadGroup();
        ThreadGroup topGroup = group;
        // 遍历线程组树,获取根线程组
        while (group != null) {
            topGroup = group;
            group = group.getParent();
        }
        // 激活的线程数加倍
        int estimatedSize = topGroup.activeCount() * 2;
        Thread[] slacks = new Thread[estimatedSize];
        //获取根线程组的所有线程
        int actualSize = topGroup.enumerate(slacks);
        Thread[] threads = new Thread[actualSize];
        System.arraycopy(slacks, 0, threads, 0, actualSize);
        return threads;
    }
}

运行后发现一个问题,在调用RunnableTest().run()方法后,发现主线程被阻塞了,并没有立即执行后面的while循环体,结果先执行了子线程中的休眠,等休眠结束后,才执行主线程的后续代码,此时,输出的所有线程中没有子线程的影子,如下:
这里写图片描述
只有一些系统线程,可是说明的是,子线程执行结束后,立马释放掉了,但问题来了,原本以为子线程的调用时异步的,不会阻塞主线程,但这里的效果是阻塞的,一时间有点不明所以,好吧,那使用Thread的方式看看效果。
2. Thread方式

class ThreadTest extends Thread{
    @Override
    public void run() {
        System.out.println("我是新启动的Thread!");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在主线程中调用new ThreadTest().start();这个时候发现,在调用后,立即执行主线程中的后续代码,并没有出现主线程阻塞的情况,而且在线程情况的输出中看到了子线程的影子,并且在子线程休眠结束后,子线程销毁掉了,运行结果如下:
这里写图片描述
可以看出,1,2时可以看到子线程的影子,在3处,由于子线程休眠结束,销毁掉了,所以没有子线程。同样可以说明,主线程中调用了子线程,子线程执行结束后,会立即销毁。但问题来了,使用Runnable.run()的方式为什么会出现阻塞主线程的情况,而Thread.start()的方式不阻塞呢?下面具体探讨下。


带着以上的疑问,将new ThreadTest().start();换成new ThreadTest().run();后,同样主线程出现阻塞,原来,不管是通过Runnable.run()还是Thread.run()运行,其实就是一个普通类方法的调用(因为实现类中有显式的run方法),当然是顺序调用的方式,而使用Thread.start()时,此时,子线程的具体执行则有系统来决定,异步执行,不阻塞主线程,至此,疑惑出现柳暗花明,哈哈,问题的发现到疑惑的解决,全是平时细节的马马虎虎,纯属庸人自扰了!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值