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 ...
随机推荐
- jQuery:详解jQuery中的事件(二)
上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...
- Javaweb学习笔记——EL表达式
一.前言 EL表达式是什么? 简而言之,可以这样理解,EL表达式全名为:Exprexxsion Language,原先是JSTL 1.0为了方便存取数据而定义的语言,到了JSTL 2.0便正式成为标准 ...
- Elasticsearch配置详解、文档元数据
目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 1.Elasticsearch配置文件详解 a. 在上面博客中,我们已经安装并且成功 ...
- AlloyRenderingEngine入门
写在前面 AlloyRenderingEngine是一款非常快速的渲染引擎,目前该项目已经合并至 https://github.com/AlloyTeam/AlloyGameEngine/ , 属于A ...
- JavaScript学习笔记7 之DOM文档对象模型
一.什么是DOMDocument Object Model 文档 -------对象 ----模型-------缩写DOM DOM是针对HTML和XML文档的一个API(应用程序编程接口).DOM描绘 ...
- javascript 实现一个回文数字
写一个方法,让"1234"变成回文数字“1234321”,就是顺着读和倒着读都是一样的:注:不让用reverse()方法: function palindrome(str){ va ...
- list集合的排序Comparator和Collections.sort
一个例子 package sortt; import java.util.ArrayList; import java.util.Collections; import java.util.Compa ...
- Android Studio 快捷键一览
刚从 eclipse 转到 android studio 的同学,编写代码时使用的快捷键不同,一时难以适应,当然可以通过设置,将快捷键模板设置成与 eclipse 相同的,但我个人不赞成,因为 And ...
- android 修改videoview的宽度和高度
如果直接用android的videoview.他是不允许你随意的修改宽度和高度的,所以我们要重写videoview! package com.hysmarthotel.view; import and ...
- Android View的几个位置坐标关系
1. View的边界,left, top, right, bottom(即左上右下),这些值都是相对View的父容器说的: 2. View的x, translationX, y, translatio ...