后台线程介绍

本文介绍了Java中的后台线程,即daemon线程,它们在程序运行时提供通用服务,但不是必不可少的部分。当所有非后台线程结束时,程序会终止并杀死后台线程。设置后台线程需在启动前调用setDaemon()方法。后台线程的子线程也将默认为后台线程。此外,后台线程在没有执行finally块的情况下可能随着最后一个非后台线程的终止而突然终止。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(下面的描述和代码摘抄自书目《java编程思想》)

所谓后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分。因此,当所有非后台线程结束时,程序也就终止了,同时会杀死所有的后台线程。反过来说,只要有任何非后台线程还在运行,程序就不会终止。比如,执行main()的就是一个非后台线程。

1.设置后台线程的方法是在线程启动之前调用setDaemon()方法

 public class SimpleDaemons implements Runnable{
     public void run(){
         try {
             while(true){
                TimeUnit.MILLISECONDS.sleep(100);
                System.out.println(Thread.currentThread() +" "+this);
             }
         } catch (InterruptedException e) {
             System.out.println("sleep() interrupted");
             e.printStackTrace();
         }
     }
     
     public static void main(String[] args)throws Exception{
         for (int i = 0; i < 10; i++) {
            Thread daemon = new Thread(new SimpleDaemons());
            daemon.setDaemon(true);//Must call before start()
            daemon.start();
        }
         System.out.println("All daemons started");
         TimeUnit.MILLISECONDS.sleep(500);//main()此时为非后台线程,其他为后台线程,所以当main()结束工作时,整个程序终止,可以修改休眠时间来观察不同的结果
     }
}

2.上述代码中的SimpleDaemons.java创建了显示的线程,以便可以设置后台标志。可以通过编写定制的ThreadFactory,有Executor创建定制的线程。代码如下:

/**1.通过实现ThreadFactory将线程全部设置为后台线程
 * */
public class DaemonThreadFactory implements ThreadFactory{

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}

/**2.创建线程
 * */
public class DaemonFromFactory implements Runnable{
     public void run(){
         try {
             while(true){
                 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(100);//Run for a while 
     }
}

这和普通的ThreadFactory的唯一区别就是它将线程的后台状态全部设置了true.

3.当一个线程被设置成了后台模式,它所派生的所有子线程全部是后台线程。代码如下(可以运行下面代码查看结果):

 public class Daemon implements Runnable{
     private Thread[] t = new Thread[10];
     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();
     }
}
public 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()+", ");
         //Allow the Daemon threads to finish their startup process
         TimeUnit.MILLISECONDS.sleep(10);
     }
}

运行结果为run()中产生的10个子线程均为后台线程,此处就不贴运行结果了。

4.后台进程在不执行finally子句的情况下就可能会终止run()方法。代码如下:

public class ADeamon implements Runnable {
     public void run(){
         try {
             System.out.println("starting ADeamon");
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            System.out.println("Exiting via InterruptedException");
        }finally{
            System.out.println("This should always run?");
        }
     }
     
     public static void main(String[] args) throws InterruptedException{
         Thread t= new Thread(new ADeamon());
         t.setDaemon(true);
         t.start();
         TimeUnit.MILLISECONDS.sleep(20);
     }
}

运行结果只打印了:starting ADeamon

但是注释掉setDaemon()的调用,就会看到finally子句执行。

这种行为是正确的,因为当最后一个非后台线程终止时,后台线程会“突然”终止,因此一旦main()退出,JVM就会立即关闭后台线程。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值