JAVA 多线程问题,主线程没有阻塞,为什么会等待子线程退出 java 1.8
学习多线程过程中,想测试isDeamon方法,但是我发现对于子线程没有设置为守护线程时,这个主线程还是会等待子线程执行完毕再结束,很奇怪,我在主线程中也没有阻塞代码,且第一时间打印了最后main方法中main done的消息,那应该可以结束了吧。
package runnable;
public class RunnableTest {
public static int flag = 0;
public static void main(String[] args){
Thread.currentThread().setPriority(10);
// 设置默认的异常处理器,全局的, 每个线程可以定义自己的默认处理器
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.toString() + "found exception: " + e.toString());
}
});
Thread t1 = new Thread(new NewMyRunnable("t1"));
// 设置线程的名字
t1.setName("My Test 1");
// 设置当该线程由于未捕获的异常而突然终止时调用的处理程序
t1.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.toString() + "found exception: " + e.toString());
}
});
t1.setPriority(1);
System.out.println(t1.toString()+t1.isDaemon());
Thread t2 = new Thread(new NewMyRunnable("t2"));
// 更改此线程的优先级。 数字越大优先级越高,优先处理,但是并不是一定优先
t2.setPriority(5);
t2.setName("My Test 2");
System.out.println(t2.toString()+t2.isDaemon());
Thread t3 = new Thread(new NewMyRunnable2("t3"));
// 更改此线程的优先级。 数字越大优先级越高,优先处理,但是并不是一定优先 范围1-10
t3.setPriority(5);
t3.setName("My Test 3");
System.out.println(t3.toString()+t3.isDaemon());
t1.start();
t2.start();
t3.start();
/*try {
// 当前线程暂停执行,参数为毫秒
Thread.sleep(1000); // 当前线程暂停执行,参数为毫秒,第二参数为纳秒,用于更高精度的停止
Thread.sleep(1000, 100); } catch (InterruptedException e) { e.printStackTrace(); }*/ System.out.println("main done "+flag);
}
}
class NewMyRunnable implements Runnable {
private String name = "";
public static int TIMES = 10;
public NewMyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
int i = 0;
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
while(i < TIMES){
if(i==TIMES-1){
throw new IllegalArgumentException("参数错误");
}
//RunnableTest.flag ++;
//System.out.println(name+": "+RunnableTest.flag); System.out.println(name +": "+ i);
// 提示调度器,我已经完成了重要工作,愿意切换线程(提示性非强制)
Thread.yield();
i++;
}
}
}
class NewMyRunnable2 implements Runnable {
private String name = "";
public static int TIMES = 10;
public NewMyRunnable2(String name) {
this.name = name;
}
@Override
public void run() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("self defined "+t.toString() + "found exception: " + e.toString());
}
});
throw new IllegalArgumentException("参数错误");
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
复制粘贴运行:
可以看到主线程已经结束了……
这是JVM规定的.有线程执行就不会退出, 除了daemon 线程.
这是控制台打印结果:
接下来,一步一步分析下。
首先,主线程启动,并启动定义的3个子线程。但是以下代码都是由主线程输出的:
说明主线程已执行完毕退出。
接下来看3个子线程。My Test 3和My Test 2的优先级比My Test 1要高,而My Test 2 需要 sleep 100000毫秒。因此My Test 3最先打印出以下代码,并执行完毕退出:
这里需要注意,My Test 3打印出来的代码是在NewMyRunnable2中定义的全局默认异常Thread.setDefaultUncaughtExceptionHandler中打印的,不是主线程中定义的全局默认异常输出的。因为主线程中的全局默认异常定义已经被NewMyRunnable2中的定义覆盖了。
接下来My Test 2的sleep时间到了,输出代码:
这里需要注意,My Test 2是NewMyRunnable的实例。而NewMyRunnable中并没有定义全局默认异常,那这行self defined……是从哪来的呢?是从NewMyRunnable2中的全局默认异常定义输出的。但是前边说了,My Test 3已经执行完毕退出了。查看setDefaultUncaughtExceptionHandler的文档可以看到这样的描述:
这样解释就通了。
接下来,轮到My Test 1执行了,并打印出如下代码:
这行是由My Test 1线程自己定义的未捕获异常处理器输出的。
到此,整个程序执行完毕。