一. java中的后台线程:
java线程大家都不陌生,可以用继承Thread类或者实现Runable接口来定义一个自己的线程。另外,java线程还可以分为前台线程(也称用户线程或普通线程)和后台线程(Daemon thread)。
1. 后台线程会随着主线程(main线程)的结束而结束,但是前台进程则不会(如果main线程先于前台进程结束,前台进程仍然会执行);或者说,只要有一个前台线程未退出,进程就不会终止。;
2. 默认情况下,程序员创建的线程是用户线程;用setDaemon(true)可以设置线程为后台线程;而用isDaemon( )则可以判断一个线程是前台线程还是后台线程;
3. jvm的垃圾回收器其实就是一个后台线程;
4. setDaemon函数必须在start函数之前设定,否则会抛出IllegalThreadStateException异常;
5.所有的“非后台线程”结束时,程序也就终止了,同时会杀死进程中所有后台线程:main就是一个非后台线程;
6.后台线程创建的子线程也是后台线程。
二、后台线程的实现:
import java.util.concurrent.TimeUnit; public class DaemonDemo implements Runnable { @Override public void run() { try { while (true) { Thread.sleep(1000); System.out.println("#" + Thread.currentThread().getName()); } } catch (InterruptedException e) { e.printStackTrace(); } finally {// 后台线程不执行finally子句 System.out.println("finally "); } } public static void main(String[] args) { for (int i = 0; i < 10; i++) { Thread daemon = new Thread(new DaemonDemo()); // 必须在start之前设置为后台线程 daemon.setDaemon(true); daemon.start(); } System.out.println("All daemons started"); try { TimeUnit.MILLISECONDS.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
运行结果:
All daemons started
#Thread-2
#Thread-3
#Thread-1
#Thread-0
#Thread-9
#Thread-6
#Thread-8
#Thread-5
#Thread-7
#Thread-4
分析:从结果可以看出,十个子线程并没有无线循环的打印,而是在主线程(main())退出后,JVM强制关闭所有后台线程。而不会有任何希望出现的确认形式,如finally子句不执行。
三、总结:
后台线程(daemon)
|——定义:指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分
| |——所有的“非后台线程”结束时,程序也就终止了,同时会杀死进程中所有后台线程:main就是一个非后台线程
|——声明并试用后台线程
| |——传统方式:通过声明线程,操作线程来定义后台线程
| | |——Thread daemon = new Thread(new TaskDaemon());//将任务交给线程也叫声明线程
| | |—— daemon.setDaemon(true);//将线程设置为后台线程
| | |——daemon.start();//启动后台线程
| |——由executor调用线程工厂:通过编写定制的ThreadFactory,可以定制由Executor创建的线程的属性
| |——1.实现ThreadFactory接口
| |——2.重写newThread方法
| |—— public Thread newThread(Runnable r){
| |—— Thread t = new Thread(r);
| |—— t.setDaemon(true);
| |—— return t;
| |—— }
| |——3.将定制的TaskDaemonFactory传递给Executor,它将用此来生成对应的线程,并操纵他们
| |—— 每个静态的ExecutorService创建方法都被重载为接受一个ThreadFactory对象,该对象将被用来创建新的线程
| |—— ExecutorService exec = Executors.newCachedThreadPool(new TaskDaemonFactory());
| |——4.将任务传递给exec,它会帮你执行线程操作
| |—— exec.execute(new TaskDaemonFromFactory());