21.2.8后台线程
1. 后台线程定义:
后台线程:是指在程序运行的时候在后台踢狗一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分。因此,当程序的非后台线程结束时,程序也就终止了,同事会杀死进程中所有的后台线程。反过来说,只要有非后台线程在运行,程序就不会终止。如:main就是一个非后台线程。
例如:
package jiangning.c21;
import java.util.concurrent.TimeUnit;
public class SimpleDeamons implements Runnable {
@Override
public void run() {
try {
TimeUnit. MILLISECONDS.sleep(100);
System. out.println(Thread.currentThread() + " : " + this);
} catch (InterruptedException e) {
System. out.println("sleep() interrupted" );
}
}
public static void main(String[] args) throws Exception {
for(int i = 0; i < 10; i++ ){
Thread daemon = new Thread(new SimpleDeamons());//创建线程
daemon.setDaemon( true);//设置线程为后台线程
daemon.start(); //启动线程
}
System. out.println("All daimons started" );
TimeUnit. MILLISECONDS.sleep(175);
}
}
/**
All daimons started
*/
解释:
1). 必须在线程启动前调用setDaemon()方法,才能设置为后台线程。
一旦main()完成其工作,就没有什么能阻止程序终止,因为除了后台线程之外,已经没有线程在运行了,因main()方法被设置为短暂休眠,所以可以看到后台线程启动的结果。
2).去掉休眠时间后执行结果:
/**
All daimons started
Thread[Thread -9,5,main] : jiangning.c21.SimpleDeamons@1ce2dd4
Thread[Thread -7,5,main] : jiangning.c21.SimpleDeamons@65a77f
Thread[Thread -0,5,main] : jiangning.c21.SimpleDeamons@1c99159
Thread[Thread -3,5,main] : jiangning.c21.SimpleDeamons@11f2ee1
Thread[Thread -2,5,main] : jiangning.c21.SimpleDeamons@a61164
Thread[Thread -4,5,main] : jiangning.c21.SimpleDeamons@3ecfff
Thread[Thread -5,5,main] : jiangning.c21.SimpleDeamons@12f0999
Thread[Thread -1,5,main] : jiangning.c21.SimpleDeamons@1ef9157
Thread[Thread -6,5,main] : jiangning.c21.SimpleDeamons@122cdb6
Thread[Thread -8,5,main] : jiangning.c21.SimpleDeamons@1d7ad1c
*/
看不到线程启动。
2. 通过编写定制的ThreadFactory可以定制由Executor创建的线程属性。
如:
package net.mindview.util;
import java.util.concurrent.*;
public class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
package jiangning.c21;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import net.mindview.util.DaemonThreadFactory;
public class DaemonFromFactory implements Runnable{
public void run(){
try {
TimeUnit. MILLISECONDS.sleep(100);
System. out.println(Thread.currentThread() + " : " + this);
} catch (InterruptedException e) {
System. out.println("interrupted" );
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors. newCachedThreadPool(new DaemonThreadFactory());
for(int i = 0; i < 10; i++){
exec.execute( new DaemonFromFactory());
}
System. out.println("All daemons started" );
TimeUnit. MILLISECONDS .sleep(500);
}
}
3.判读是否为后台线程的方法:用isDaemon()。
如果是一个后台线程,那么由它创建的线程都是后台线程。
package jiangning.c21;
import java.util.concurrent.TimeUnit;
class Daemon implements Runnable{
private Thread[] t = new Thread[10];
@Override
public void run() {
for(int i = 0; i<t.length; i++){
t[i] = new Thread(new DaemonSpawn());
t[i].start();
System. out.println("DaemonSpawn " + i + " started" );//打印出执行了那个线程
}
for(int i = 0; i < t.length; i++){
System. out.println("t[" + i + "].isDaemon " +t[i].isDaemon());//打印线程是否为后台线程
}
while(true ){
Thread. yield();
}
}
}
class DaemonSpawn implements Runnable{
public void run(){
while(true ){
Thread. yield();
}
}
}
public class Daemons {
public static void main(String[] args) throws Exception {
Thread d = new Thread(new Daemon());
d.setDaemon( true);
d.start();
System. out.println("d.isDaemon()= " + d.isDaemon()+",");
TimeUnit. MILLISECONDS.sleep(1);
}
}
/**
d.isDaemon()= true,
DaemonSpawn 0 started
DaemonSpawn 1 started
DaemonSpawn 2 started
DaemonSpawn 3 started
DaemonSpawn 4 started
DaemonSpawn 5 started
DaemonSpawn 6 started
DaemonSpawn 7 started
DaemonSpawn 8 started
DaemonSpawn 9 started
t[0].isDaemon true
t[1].isDaemon true
t[2].isDaemon true
t[3].isDaemon true
t[4].isDaemon true
t[5].isDaemon true
t[6].isDaemon true
t[7].isDaemon true
t[8].isDaemon true
t[9].isDaemon true
*/
解释:
Thread d = new Thread( new Daemon());
d.setDaemon( true );
创建Daemon对象d为后台线程。
所以在d中创建的线程都是后台线程。
4.后台线程在不执行finally子句的情况下终止run()方法。
例子:
package jiangning.c21;
import java.util.concurrent.TimeUnit;
/**
* finally子句不会执行。
* @author jn
*
*/
class ADaemon implements Runnable{
@Override
public void run() {
try {
System. out.println("ADaemon started" );
TimeUnit. MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
System. out.println("This should always run?" );
}
}
}
public class DaemonsDonotRunFinally {
public static void main(String[] args) {
Thread t = new Thread(new ADaemon());
t.setDaemon( true);
t.start();
}
}
/**
* ADaemon started
*/
总结:
1)后台线程的定义及如何设置后台线程。
2)通过创建后台线程
3)判断是否为后台线程
4)后台线程可以不执行finally而终止run()方法。