java并发编程学习: 守护线程(Daemon Thread)
在正式理解这个概念前,先把 守护线程 与 守护进程 这二个极其相似的说法区分开,守护进程通常是为了防止某些应用因各种意外原因退出,而在后台独立运行的系统服务或应用程序。 比如:我们开发了一个邮件发送程序,一直不停的监视队列池,发现有待发送的邮件,就将其发送出去。如果这个程序挂了(或被人误操作关了),邮件就不发出去了,为了防止这种情况,再开发一个类似windows 系统服务的应用,常驻后台,监制这个邮件发送程序是否在运行,如果没运行,则自动将其启动。
而我们今天说的java中的守护线程(Daemon Thread) 指的是一类特殊的Thread,其优先级特别低(低到甚至可以被JVM自动终止),通常这类线程用于在空闲时做一些资源清理类的工作,比如GC线程,如果JVM中所有非守护线程(即:常规的用户线程)都结束了,守护线程会被JVM中止,想想其实也挺合理,没有任何用户线程了,自然也不会有垃圾对象产生,GC线程也没必要存在了。
实际开发中,也可以手动将线程设置为Daemon Thread,只有一个限制:必须在线程的start方法设置,见下面的示例:
package test; public class Program { public static void main(String[] args) {
TestThread t1 = new TestThread();
t1.setDaemon(true);
t1.start();
} private static class TestThread extends Thread {
public void run() {
System.out.println("test");
}
}
}
由于t1设置成Daemon Thread了,运行后,main进程马上就结束,此时没有用户进程在运行,守护进程默认是不执行的,因此运行后,没有任何输出结果,符合我们刚才的解释。
注:在idea等集成IDE环境下测试时,如果多次点击Run按钮,可能会发现第二次运行时,偶尔也会输出test,估计是ide里上次运行后的java进程并未完全退出,可以手动把windows进程中的所有java.exe进程干掉再测试。
如果把t1.setDaemon(true);这一行注释掉,就会输出test了。
另外,如果把main函数最后加一行阻塞的代码,比如:
public static void main(String[] args) throws IOException {
TestThread t1 = new TestThread();
t1.setDaemon(true);
t1.start();
System.in.read();
}
加了一行System.in.read()后,再运行,会发现test会输出,这是因为main这个用户线程被阻塞了,JVM发现有用户进程在运行,守护进程才能机会被执行。
再来一个复杂点的示例:
假设有二个线程,一个是常规的用户线程,不停写入日志,另一个是守护线程,在空闲时清理日志(仅保留最近的5条日志)
package test; import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; public class Program { private static int queueCapacity = 10;
private static BlockingQueue<String> logQueue = new ArrayBlockingQueue<String>(queueCapacity); public static void main(String[] args) throws IOException { LogWriter writer = new LogWriter();
LogCleaner cleaner = new LogCleaner();
cleaner.setDaemon(true); writer.start();
cleaner.start();
} /**
* 模拟不停写日志(直到队列写满)
*/
private static class LogWriter extends Thread {
public void run() {
for (int i = 0; i < queueCapacity; i++) {
try {
logQueue.put("" + i);
System.out.println("日志已写入,当前日志内容:" + logQueue);
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} /**
* 模拟在空闲时清理日志(仅保留5条日志)
*/
private static class LogCleaner extends Thread {
public void run() {
while (true) {
if (logQueue.size() > 5) {
try {
logQueue.take();
System.out.println("多余日志被清理,当前日志内容:" + logQueue);
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
运行结果:
日志已写入,当前日志内容:[]
日志已写入,当前日志内容:[, ]
日志已写入,当前日志内容:[, , ]
日志已写入,当前日志内容:[, , , ]
日志已写入,当前日志内容:[, , , , ]
日志已写入,当前日志内容:[, , , , , ]
多余日志被清理,当前日志内容:[, , , , ]
日志已写入,当前日志内容:[, , , , , ]
多余日志被清理,当前日志内容:[, , , , ]
日志已写入,当前日志内容:[, , , , , ]
多余日志被清理,当前日志内容:[, , , , ]
日志已写入,当前日志内容:[, , , , , ]
多余日志被清理,当前日志内容:[, , , , ]
日志已写入,当前日志内容:[, , , , , ]
多余日志被清理,当前日志内容:[, , , , ]
参考文章:
http://ifeve.com/thread-management-8/
http://www.cnblogs.com/super-d2/p/3348183.html
java并发编程学习: 守护线程(Daemon Thread)的更多相关文章
- Java并发编程学习:线程安全与锁优化
本文参考<深入理解java虚拟机第二版> 一.什么是线程安全? 这里我借<Java Concurrency In Practice>里面的话:当多个线程访问一个对象,如果不考虑 ...
- JAVA并发编程学习笔记------线程的三种创建方式
创建线程一般有如下几个方式: 1. 通过继承Thread类来创建一个线程: /** * 步骤1:定义一个继承Thread类的子类 * 步骤2:构造子类的一个对象 * 步骤3:启动线程: * */ pu ...
- JAVA并发编程——守护线程(Daemon Thread)
在Java中有两类线程:用户线程 (User Thread).守护线程 (Daemon Thread). 所谓守护 线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称 ...
- JAVA - 守护线程(Daemon Thread)
转载自:http://www.cnblogs.com/luochengor/archive/2011/08/11/2134818.html 在Java中有两类线程:用户线程 (User Thread) ...
- 守护线程(Daemon Thread)
在Java中有两类线程:用户线程 (User Thread).守护线程 (Daemon Thread). 所谓守护 线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称 ...
- 用户线程 (User Thread)、守护线程 (Daemon Thread)
在Java中有两类线程:用户线程 (User Thread).守护线程 (Daemon Thread). 所谓守护 线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称 ...
- Java并发编程系列-(2) 线程的并发工具类
2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...
- Java并发编程学习前期知识下篇
Java并发编程学习前期知识下篇 通过上一篇<Java并发编程学习前期知识上篇>我们知道了在Java并发中的可见性是什么?volatile的定义以及JMM的定义.我们先来看看几个大厂真实的 ...
- Java并发编程学习笔记
Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...
随机推荐
- [Cordova] Plugin里使用iOS Framework
[Cordova] Plugin里使用iOS Framework 前言 开发Cordova Plugin的时候,在Native Code里使用第三方Library,除了可以加速项目的时程.也避免了重复 ...
- JavaScript中数组去除重复
方式一:常规模式 1.构建一个新的临时数组存放结果 2.for循环中每次从原数组中取出一个元素,用这个元素循环与临时数组对比 3.若临时数组中没有该元素,则存到临时数组中 //方式一: Array.p ...
- Meta标签详解(HTML JAVASCRIPT)
Meta标签详解,在网上转的,希望对大家有用 您的个人网站即使做得再精彩,在“浩瀚如海”的网络空间中,也如一叶扁舟不易为人发现,如何推广 个人网站,人们首先想到的方法无外乎以下几种: ● 在搜索引擎中 ...
- javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的。
javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的. 1 function getUrl(tp) { if (tp == 'd') { ...
- ORACLE告警日志文件
告警日志介绍 告警日志文件是一类特殊的跟踪文件(trace file).告警日志文件命名一般为alert_<SID>.log,其中SID为ORACLE数据库实例名称.数据库告警日志是按时间 ...
- Could not obtain information about Windows NT group/user 'xxxx\xxxx', error code 0x5
案例描述 昨晚踢球回来,接到电话说一个系统的几个比较重要作业出错,导致系统数据有些问题.让我赶紧检查看看.检查作业日志时发现,作业报如下错误(关键信息用xxx替换) The job failed. ...
- SQLite学习笔记(八)&&sqlite实现架构
该系列的前面一些文章我重点讲了sqlite的核心功能,比如封锁机制,共享缓存,以及事务管理等.但对于sqlite的整体没有作一个全面的介绍,本文将从实现的层面,整体介绍sqlite的框架.各个核心模块 ...
- SQL Server 2008 R2——使用FULL OUTER JOIN实现多表信息汇总
=================================版权声明================================= 版权声明:原创文章 谢绝转载 请通过右侧公告中的“联系邮 ...
- mysql在linux下的安装
安装环境:系统是 centos6.5 1.下载 下载地址:http://dev.mysql.com/downloads/mysql/5.6.html#downloads 下载版本:我这里选择的5.6. ...
- netty4虚拟内存不断飙升
去年升级过一个老的netty3的程序到netty4,近期突然注意到一个问题,就是这个程序随着时间虚拟内存会不断升高.之前升级的时候担心存在内存泄露,所以还特意用jstate跟踪过gc回收的情况,并没有 ...