java启动线程的方法(java同时启动两个线程去执行)
定义和概述
java 中的线程分为两类,分别为daemon 线程(守护线程〉和user 线程(用户线程)。守护线程又称daemon线程,运行在后台,看不见;用户线程运行在前台,看的见。
在jvm启动时会调用main 函数, main 函数所在的线程就是一个用户线程,其实在jvm内部同时-还启动了好多守护线程, 比如垃圾回收线程。
daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这意味着,当一个java虚拟机中不存在非daemon线程的时候,java虚拟机将会退出,而不管当前是否有守护线程,也就是说守护线程是否结束并不影响jvm的退出。
实际上,在main线程运行结束后,jvm会自动启动一个叫作destroyjavavm 的线程,该线程会等待所有用户线程结束后终止jvm 进程。
在tomcat的nio实现nioendpoint中会开启一组接受线程来接受用户的连接请求,以及一组处理线程负责具体处理用户请求,在默认情况下,接受线程和处理线程都是守护线程,这意味着当tomcat 收到shutdown 命令后并且没有其他用户线程存在的情况下tomcat 进程会马上消亡,而不会等待处理线程处理完当前的请求。
2 使用守护线程
在线程start之前,可以通过调用thread.setdaemon(true)将线程设置为daemon线程。
守护线程有两种结束方式:
- 守护线程也具有自己的run();方法,当后台线程完成自己的run方法后,守护线程结束。
- 用户线程运行结束,守护线程自动结束。
3 测试案例
public class daemon {
//启动该类,将会构造两条线程,main线程和一条子线程。
public static void main(string[] args) throws interruptedexception {
//测试非守护线程
//可以看到,输出"main线程结束"之后,子线程还在继续输出,程序没有结束
// test1();
//测试守护线程
//可以看到,输出"main线程结束"之后,子线程没有继续输出,程序结束
test2();
}
/**
* 测试非守护线程
*
* @throws interruptedexception
*/
public static void test1() throws interruptedexception {
thread thread = new thread(() -> {
while (true) {
try {
thread.currentthread().sleep(500);
} catch (interruptedexception e) {
e.printstacktrace();
}
system.out.println("子线程非守护线程");
}
});
thread.start();
thread.currentthread().sleep(1000);
system.out.println("main线程结束");
}
//测试守护线程
public static void test2() throws interruptedexception {
thread thread = new thread(() -> {
while (true) {
try {
thread.currentthread().sleep(500);
} catch (interruptedexception e) {
e.printstacktrace();
}
system.out.println("子线程守护线程");
}
});
thread.setdaemon(true);
thread.start();
thread.currentthread().sleep(1000);
system.out.println("main线程结束");
}
}
复制代码
使用jps查看java进程,可以发现如果子线程是守护线程那么主线程结束,子线程也结束了;如果子线程不是守护线程那么主线程结束,子线程没有结束。
4 注意事项
daemon线程被用作完成支持性工作,但是在java虚拟机退出时daemon线程中的finally块并不一定会执行,如下代码:
public class daemon {
public static void main(string[] args) {
thread thread = new thread(new daemonrunner(), "daemonrunner");
thread.setdaemon(true);
thread.start();
}
static class daemonrunner implements runnable {
@override
public void run() {
try {
sleeputils.second(10);
} finally {
system.out.println("daemonthread finally run.");
}
}
}
}
复制代码
运行daemon程序,可以看到在控制台上没有任何输出。main线程(非daemon线程)在启动了线程daemonrunner之后随着main方法执行完毕而终止,而此时java虚拟机中已经没有非daemon线程,虚拟机需要退出。java虚拟机中的所有daemon线程都需要立即终止,因此daemonrunner立即终止,但是daemonrunner中的finally块并没有执行。
在构建daemon线程时,不能依靠finally块中的内容来确保执行关闭或清理资源的逻辑。
下一篇: 微信好友添加到桌面的图文教程
推荐阅读
-
java启动线程的方法(线程池启动线程的方式)
-
java启动线程的方法(java同时启动两个线程去执行)
-
java启动线程的方法(java同时启动两个线程去执行)
-
java启动线程的方法(线程池启动线程的方式)
-
java多线程设计模式(1) 线程的创建和启动
-
java多线程设计模式(1) 线程的创建和启动
-
java启动线程的几种方式(揭晓java启动线程的方法)
-
将插入、冒泡排序算法设计成线程,启动两个以上不同的线程同时运行,计算不同排序 的运行时间。
-
Java~在使用isAlive时, 将线程对象已构造参数的形式传递给Thread对象时进行start启动时, 使用this和Thread.currentThread的差异
-
设计窗口界面,包含一个启动按钮,和两个文本框,单击启动按钮后,执行打印输出字符a和数字的多线程代码,每次在控制台打印输出字符时,同时在窗口中不同的文本框中追加显示出来。