java线程在http://blog.youkuaiyun.com/okiwilldoit/article/details/50801321 已经介绍了,可以用继承Thread类或者实现Runable接口来定义一个自己的线程。本文介绍java线程的分类。
java线程可以分为用户线程(也称前台线程或普通线程)和后台线程(Daemon thread);
后台线程并不属于程序中不可或缺的部分,当所有的非后台线程结束时,程序也就终止了,同时会杀死所有后台线程。
两者的区别是:
后台线程会随着主程序的结束而结束,但是用户进程则不会;或者说,只要有一个用户线程未退出,进程就不会终止;
后台线程在不执行finally子句的情况下就会终止其run方法。后台线程创建的子线程也是后台线程。
默认情况下,程序员创建的线程是用户线程;用setDaemon(true)可以设置线程为后台线程;而用isDaemon( )则可以判断一个线程是前台线程还是后台线程;
jvm的垃圾回收器其实就是一个后台线程;
setDaemon函数必须在start函数之前设定,否则会抛出IllegalThreadStateException异常;
实例一代码:
线程类:
public class DaemonDemo implements Runnable{
public void run() {
try {
while (true) {
Thread.sleep(1000);
System.out.println("#" + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {// 后台线程不执行finally子句
System.out.println("finally ");
}
}
}
主程序:
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread daemon = new Thread(new DaemonDemo());
// 必须在start之前设置为后台线程
daemon.setDaemon(true);
daemon.start();
}
System.out.println("All daemons started");
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
输出结果:
All daemons started
#Thread-3
#Thread-4
#Thread-0
#Thread-2
#Thread-1
可以看出,后台线程的while循环并未一直执行下去,而是随着主进程的结束,而退出了。同时主程序结束,后台线程中的finally里的代码也不会执行。
实例二代码:
上文是设置单个线程为后台线程,下面的代码是设置线程池中的线程全部为后台线程。
ExecutorService threadPool = Executors.newCachedThreadPool(new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});
for(int i=0; i<5; i++) {
threadPool.execute(new DaemonDemo());
}