关于Thread的start和run方法的执行方式
今天突然想到,在主线程中启动一个子线程,在子线程执行完毕后,是否可以自动销毁的疑惑,带着问题,开始考虑编码,在编码过程中分别使用了Runnable和Thead两种不同的方式,下面先看第一中Runnable方式。
- 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()时,此时,子线程的具体执行则有系统来决定,异步执行,不阻塞主线程,至此,疑惑出现柳暗花明,哈哈,问题的发现到疑惑的解决,全是平时细节的马马虎虎,纯属庸人自扰了!
原文地址: https://blog.csdn.net/yuxiao97/article/details/80037780
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章