java可以设置一个线程是否是后台线程。后台线程通常作为一种服务线程而存在,并不是程序不可或缺的一部分。当所有的非后台线程退出时,整个程序也就退出了,而且会关闭进程中的所有后台线程。所以,如果在后台线程中有finally语句,则不一定会执行。看下面的例子:
package org.fan.learn.thread.deamon;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Created by fan on 16-6-7.
*/
public class ADaemon implements Runnable {
public void run() {
System.out.println( Thread.currentThread() + "IsDaemon :" + Thread.currentThread().isDaemon() );
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Daemon exits");
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
Thread t = new Thread(new ADaemon());
t.setDaemon(true);
executorService.execute(t);
}
executorService.shutdown();
}
}
输出如下所示:
Thread[pool-1-thread-1,5,main]IsDaemon :false
Thread[pool-1-thread-3,5,main]IsDaemon :false
Thread[pool-1-thread-2,5,main]IsDaemon :false
Thread[pool-1-thread-4,5,main]IsDaemon :false
Thread[pool-1-thread-5,5,main]IsDaemon :false
Daemon exits
Daemon exits
Daemon exits
Daemon exits
Daemon exits
上面这种写法并没有将线程置为后台线程。
当使用Thread来启动线程时可以这么写:
package org.fan.learn.thread.deamon;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Created by fan on 16-6-7.
*/
public class ADaemon implements Runnable {
public void run() {
System.out.println( Thread.currentThread() + "IsDaemon :" + Thread.currentThread().isDaemon() );
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Daemon exits");
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++) {
Thread t = new Thread(new ADaemon());
t.setDaemon(true);
t.start();
}
}
}
输出如下所示:
Thread[Thread-0,5,main]IsDaemon :true
Thread[Thread-1,5,main]IsDaemon :true
Thread[Thread-2,5,main]IsDaemon :true
Thread[Thread-3,5,main]IsDaemon :true
注意,上面的有一个线程没有执行,驱动main的线程已经退出了。
使用Executor方式启动线程,需要给Executor传递ThreadFactory。
package org.fan.learn.thread.deamon;
import java.util.concurrent.ThreadFactory;
/**
* Created by fan on 16-6-7.
*/
public class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
}
package org.fan.learn.thread.deamon;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Created by fan on 16-6-7.
*/
public class ADaemon implements Runnable {
public void run() {
System.out.println( Thread.currentThread() + "IsDaemon :" + Thread.currentThread().isDaemon() );
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Daemon exits");
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool(new DaemonThreadFactory());
for (int i = 0; i < 5; i++) {
executorService.execute(new ADaemon());
}
executorService.shutdown();
}
}
输出如下所示:
Thread[Thread-0,5,main]IsDaemon :true
Thread[Thread-1,5,main]IsDaemon :true
Thread[Thread-2,5,main]IsDaemon :true
Thread[Thread-3,5,main]IsDaemon :true
Thread[Thread-4,5,main]IsDaemon :true
至于Daemon Thread怎么正常退出,后面再续。
在《Thinking in java》第四版的21.2.8末尾有这么一句话:Executor控制的所有任务可以同时被关闭。 不懂!