Java后台线程(daemon)

什么是后台线程?

       "后台线程是指程序运行时在后台提供一种通用服务的线程,且这种线程不属于程序中不可或缺的一部分"。

       后台线程也称为守护线程 (比如JVM处理垃圾回收 使用的就是后台线程),  我们创建的线程一般用于处理我们自己的某些任务,而后台线程主要用于一些公共的任务以提供服务。

       我们创建的线程可以在start()启动前使用  thread.setDaemon(true); 来将其设置为后台线程,使用isDaemon()来判断线程是否为后台线程。

什么是非后台线程?

       这句有点废话了,其实除了后台线程外其他线程都属于非后台线程,比如main函数启动运行时创建的线程。

后台线程非后台线程还有一个区别在于, 非后台线程全部结束时表示此时程序运行结束,那么后台线程将会被全部终止。 如果非后台线程还在运行,那么那些后台线程也不会被终止。 再拿垃圾回收机制来讲,如果程序都结束了,那么JVM的垃圾回收的线程一定也会终止。

简单的案例:

     在此案例中,main函数创建了十个线程,并将这些线程设置为后台线程setDaemon(true),这十个后台线程将会在run()中睡眠150毫秒然后打印出当前线程的信息,而main将会在创建完线程后睡眠175毫秒,因此这些后台线程虽然睡眠了150毫秒,但时间仍足够打印出信息。

import java.util.concurrent.TimeUnit;


/**
 * 
 * @author Administrator
 *
 * main是一个非后台线程,main结束运行后(即非后台线程结束后),将会结束所有后台线程,终止程序运行
 * 
 * 反过来讲,只要任何非后台线程还在运行,程序将不会结束
 *
 */
public class test {
	public static void main(String[] args) throws Exception {

		for (int i = 0; i < 10; i++) {
			Thread daemon = new Thread(new MyThread());
			daemon.setDaemon(true);//设置为后台线程
			daemon.start();
		}
		System.out.println("Thread create end!");
		
		TimeUnit.MILLISECONDS.sleep(175);//main线程将会在175毫秒后结束,如果有线程在这时间内没有打印出信息,那么也将会被终止

	}
}


class MyThread implements Runnable{

	@Override
	public void run() {
		try {
			
			TimeUnit.MILLISECONDS.sleep(150);//后台线程睡眠150毫秒
			System.out.println(Thread.currentThread()+" : " + this);//打印信息
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

打印出的信息:

Thread create end!
Thread[Thread-9,5,main] : com.yangsw.test1.MyThread@43cdad4b
Thread[Thread-6,5,main] : com.yangsw.test1.MyThread@5e70125b
Thread[Thread-2,5,main] : com.yangsw.test1.MyThread@5b152f18
Thread[Thread-0,5,main] : com.yangsw.test1.MyThread@9f34d54
Thread[Thread-4,5,main] : com.yangsw.test1.MyThread@33bbe97
Thread[Thread-8,5,main] : com.yangsw.test1.MyThread@35af3a51
Thread[Thread-5,5,main] : com.yangsw.test1.MyThread@12ceba90
Thread[Thread-1,5,main] : com.yangsw.test1.MyThread@627d1747
Thread[Thread-3,5,main] : com.yangsw.test1.MyThread@1f5f791b
Thread[Thread-7,5,main] : com.yangsw.test1.MyThread@70e25c99

但是,如果我们将这些后台线程的睡眠时间,从150增加到大于175 (比如180或者200), 那么那些后台线程的信息将不会被打印出来,因为main线程在175毫秒睡眠后结束了运行,此时唯一的非后台线程运行结束,整个程序也将结束,无论后台线程此时在做什么都将会被终止。

将run()中后台线程的时间修改后:

@Override
	public void run() {
		try {
			
				TimeUnit.MILLISECONDS.sleep(180);//后台线程睡眠180毫秒
				System.out.println(Thread.currentThread()+" : " + this);//打印信息
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

 

打印出的信息:

Thread create end!

        此时后台线程的信息都不能打印出来,因为在他们睡眠的180毫秒时间里,main已经苏醒并结束了程序运行。

        我们还可以把后台线程的睡眠时间设置为和main相同的175,这样打印信息时你会发现,有部分线程的信息会被打印出来,因为在很短的时间内,部分后台线程在和main同时苏醒后打印出了信息,但是更多的后台线程来不及打印就已经被终止。

非后台线程案例:

      如果在以上代码中,我们不将创建的线程设置为后台线程以用户线程(也就是非后台线程)的身份进行信息打印的任务,那么无论怎样,信息一定会被打印出来, 虽然main线程已经结束了,但是用户创建的线程身份也为非后台线程,所以将会继续执行,打印出信息,而这些线程打印完毕后结束,此时已经没有非后台线程在运行了,程序最终终止。

修改后的代码:

     代码修改后,main将会创建3个线程,但并没有把他们设置为后台线程,main线程在创建完用户线程后将直接结束,而那些每个用户线程将会在run中循环5次,每次睡眠1秒然后打印信息。 

import java.util.concurrent.TimeUnit;



public class test {
	public static void main(String[] args) throws Exception {

		for (int i = 0; i < 3; i++) {
			Thread daemon = new Thread(new MyThread());
//			daemon.setDaemon(true);//设置为后台线程
			daemon.start();
		}
		System.out.println("Thread create end!");
		
//		TimeUnit.MILLISECONDS.sleep(175);//main线程将会在175毫秒后结束,如果有线程在这时间内没有打印出信息,那么也将会被终止

	}
}


class MyThread implements Runnable{
	int i = 0;

	@Override
	public void run() {
		try {
			
			while(i<5) {
				TimeUnit.MILLISECONDS.sleep(1000);//后台线程睡眠1000毫秒
				System.out.println(Thread.currentThread()+" : " + this);//打印信息
				i++;
			}
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

打印出的信息:

Thread create end!
Thread[Thread-2,5,main] : com.yangsw.test1.MyThread@627d1747
Thread[Thread-1,5,main] : com.yangsw.test1.MyThread@9f34d54
Thread[Thread-0,5,main] : com.yangsw.test1.MyThread@6e1ecd8e
Thread[Thread-0,5,main] : com.yangsw.test1.MyThread@6e1ecd8e
Thread[Thread-1,5,main] : com.yangsw.test1.MyThread@9f34d54
Thread[Thread-2,5,main] : com.yangsw.test1.MyThread@627d1747
Thread[Thread-1,5,main] : com.yangsw.test1.MyThread@9f34d54
Thread[Thread-0,5,main] : com.yangsw.test1.MyThread@6e1ecd8e
Thread[Thread-2,5,main] : com.yangsw.test1.MyThread@627d1747
Thread[Thread-0,5,main] : com.yangsw.test1.MyThread@6e1ecd8e
Thread[Thread-2,5,main] : com.yangsw.test1.MyThread@627d1747
Thread[Thread-1,5,main] : com.yangsw.test1.MyThread@9f34d54
Thread[Thread-0,5,main] : com.yangsw.test1.MyThread@6e1ecd8e
Thread[Thread-2,5,main] : com.yangsw.test1.MyThread@627d1747
Thread[Thread-1,5,main] : com.yangsw.test1.MyThread@9f34d54

     因为用户线程也都是非后台线程, 只要非后台线程还在运行,程序将不会终止

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值