后台线程(daemon)
所谓后台线程(daemon),是指程序在运行时提供的一种通用线程服务,这种线程并不属于程序中不可或缺的部分。因此,所有的非后台线程结束后,程序也就会终结所有的线程,同时会杀死所有的后台现场。也就是说,程序中只要有后台线程还在运行,那么程序就不会终止。比如,执行main()方法就是一个非后台线程。
public class DaemonThread implements Runnable{
@Override
public void run() {
while (true){
try {
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(Thread.currentThread() +" " + this);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
for(int i = 0 ; i< 10 ;i ++ ){
Thread thread = new Thread(new DaemonThread());
thread.setDaemon(true);
thread.start();
}
System.out.println("All dacmoi start!");
TimeUnit.MILLISECONDS.sleep(1000);
}
}
这里的thread.setDaemon(true);就是把一个线程的daemon属性设置为true,那么系统就会认为她是一个后台线程。当main()方法运行完毕后,就一切终止了,包括后台线程。但是如果在main()方法中最后一句加上sleep让它休眠,那么你就会看到后台线程开始运行。这样就是显式的创建了一个后台线程。
同时可以使用ThreadFactory隐式的创建后台线程。
public class DaemonThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
/**
* 后台线程,main方法结束后,便马上结束
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ExecutorService service = Executors.newCachedThreadPool(new DaemonThreadFactory());
for(int i = 0 ;i < 10;i++){
service.execute(new DaemoinFromFactory());
}
service.shutdown();
System.out.println("test");
TimeUnit.MILLISECONDS.sleep(167);
}
}
DaemonThreadFactory 要使用线程池Executors来配合使用,唯一的差异化就是把你提供的线程都隐式的设置为deaemon=true,每个静态的ExecutorService 都可以接受一个ThreadFactory对象。而这个对象将被默认的创建新的线程。也可以通过isDaemon()判断一个线程是否是一个后台线程
如果一个线程被设置为后台线程,但是它里面派生了很多子线程,那么派生的子线程也会设置为后台线程。
public class DaemonMoney implements Runnable{
private Thread[] t = new Thread[10];
@Override
public void run() {
for(int i = 0 ;i < 10;i ++){
t[i] = new Thread(new SpanwThread());
t[i].start();
System.out.println("Daemo span " + i + " start !");
}
for(int i = 0 ;i < t.length;i ++){
System.out.println("t{ " + i + "] .isDamon " + t[i].isDaemon() + " .");
}
while (true){
Thread.yield();
}
}
public static void main(String[] args) throws InterruptedException {
Thread d = new Thread(new DaemonMoney());
d.setDaemon(true);
d.start();
System.out.println("d.isDeamon " + d.isDaemon() + " .");
TimeUnit.MILLISECONDS.sleep(100);
}
}
class SpanwThread implements Runnable{
@Override
public void run() {
while (true){
Thread.yield();
}
}
}
后台线程中若是存在finally()方法,猜会不会执行呢??
答案是不会执行,因为即便finally这种行为是正确的,但是情况依然如此,当最后一个后台线程终止时,后台线程会突然终止,因此一旦main()结束,那么所有的线程都将结束。而不会有你的希望出现的确认形式。因此,你不能优雅的关闭所有的后台线程,使用Exectuor是一种更好的方式。