Java多线程:守护线程与非守护线程的详解
什么是守护线程?
在Java多线程中,守护线程是一种在后台运行的线程,它不会阻止程序的结束,也不会执行任何没有被其他非守护线程阻止的操作。
换句话说,当程序中最后一个非守护线程结束时,JVM会强制退出来,即使守护线程还在运行。
如何创建守护线程?
可以通过Thread类的setDaemon()方法来创建守护线程,示例如下:
Thread daemonThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("I'm a daemon thread!");
}
}
});
daemonThread.setDaemon(true);
daemonThread.start();
在上述代码中,创建了一个无限循环的守护线程,当程序中最后一个非守护线程结束时,守护线程也将停止运行。
如何创建非守护线程?
非守护线程是线程默认创建的类型。如果一个线程没有被设置为守护线程,那么它就是非守护线程。
示例如下:
Thread nonDaemonThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("I'm a non-daemon thread!");
}
}
});
nonDaemonThread.start();
在上述代码中,创建了一个无限循环的非守护线程。
守护线程和非守护线程的区别
主要区别在于程序结束时守护线程和非守护线程的行为不同。
当程序中最后一个非守护线程结束时,JVM会强制退出来,即使守护线程还在运行。而非守护线程执行完它的任务后,程序才会退出。
此外,守护线程还有一个特点,它不会阻止JVM的正常关闭。
示例说明1:使用守护线程实现自动保存功能
public class AutoSaveThread extends Thread {
private boolean changed = false;
public void setChanged() {
this.changed = true;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (changed) {
System.out.println("自动保存");
changed = false;
}
}
}
public static void main(String[] args) throws Exception {
AutoSaveThread autoSaveThread = new AutoSaveThread();
autoSaveThread.setDaemon(true);
autoSaveThread.start();
for (int i = 0; i < 5; i++) {
System.out.println("Main thread working...");
Thread.sleep(1000);
autoSaveThread.setChanged();
}
}
}
在上述代码中,创建了一个存储是否发生变更的布尔值变量changed的AutoSaveThread守护线程。在运行时,守护线程每秒检查一次是否有发生变更,有变更则自动保存。在主线程中执行5次循环时,每次循环后都将changed设为true,以用于守护线程的条件判断。
运行该程序时,即使主线程已经结束,但守护线程会一直运行下去。
示例说明2:使用非守护线程下载文件
public class DownloadThread implements Runnable {
private String url;
private String fileName;
public DownloadThread(String url, String fileName) {
this.url = url;
this.fileName = fileName;
}
@Override
public void run() {
try {
URL downLoadUrl = new URL(url);
URLConnection conn = downLoadUrl.openConnection();
InputStream is = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(fileName);
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.close();
is.close();
System.out.println(fileName + " 下载完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Thread(new DownloadThread("http://cdn.npm.taobao.org/dist/node/v10.15.1/node-v10.15.1.pkg", "node-v10.15.1.pkg")).start();
new Thread(new DownloadThread("http://sw.bos.baidu.com/sw-search-sp/software/8c18ae9d1d1e7/SogouInput_mac_10.1.0.1338.dmg", "SogouInput_mac_10.1.0.1338.dmg")).start();
}
}
在上述代码中,创建了一个非守护线程DownloadThread来实现下载文件。在main方法中,同时执行了两个DownloadThread实例,在两个线程中分别下载了node.js和搜狗输入法的安装包。
在下载完成后,程序仍然不会退出,因为这里使用的是非守护线程。
总结
通过本文,我们详细讲解了Java多线程中守护线程和非守护线程的概念和用法,并给出了多个示例。掌握了守护线程和非守护线程的使用方法,可以帮助我们更好的进行多线程编程。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:【java 多线程】守护线程与非守护线程的详解 - Python技术站