多线程学习(四)

让步

yield() 给线程调度机制一个暗示:你的工作已经做得差不多了,可以让别的线程使用cpu了.这只是一个暗示,没有任何机制保证它会被采纳。

后台线程

后台线程是指程序执行时候,在后台提供一种通用服务的线程。并且这种线程并不属于程序的不可缺少的一部分。因此当所有的非后台线程结束时,程序也就截止了,同时也会杀死进程中所有后台线程。例如 main()就是一个非后台线程

package thread.test1;

import java.util.concurrent.TimeUnit;

public class SimpleDaemons implements Runnable {

	@Override
	public String toString() {
		return Thread.currentThread().getName();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			try {
				TimeUnit.MILLISECONDS.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(this);
		}
	}

	public static void main(String[] args) throws InterruptedException {
		for(int i=0;i<10;i++){
			Thread t=new Thread(new SimpleDaemons());
			t.setDaemon(true);
			t.start();
		}
		System.out.println("all daemons started!");
		TimeUnit.MILLISECONDS.sleep(1200);
		System.out.println("main over");
	}
}
all daemons started!
Thread-6
Thread-3
Thread-8
Thread-9
Thread-0
Thread-5
Thread-4
....
Thread-6
Thread-2
main over
Thread-1
Thread-5
Thread-9

这里是显示的设置线程为后台线程,当然也可以通过定制ThreadFactory定制由Executor创建的线程的属性(这句话拗口)代码如下:
定制的ThreadFactory:

public class DaemonThreadFactory implements ThreadFactory {

	@Override
	public Thread newThread(Runnable r) {
		// TODO Auto-generated method stub
		Thread t=new Thread(r);
		t.setDaemon(true);
		return t;
	}

}
public class DaemonFromFactory implements Runnable {
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return super.toString();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		while(true){
			try {
				TimeUnit.MILLISECONDS.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(this);
		}
	}
	public static void main(String[] args) throws Exception {
		ExecutorService exec=Executors.newCachedThreadPool(new DaemonThreadFactory()); //通过ThreadFactory 定制ExecutorService
		for(int i=0;i<5;i++){
			exec.execute(new DaemonFromFactory());
		}
		System.out.println("all daemon run!");
		TimeUnit.MILLISECONDS.sleep(1200);
	}

}

也可通过继承ThreadPoolExecutor加定制ThreadFactory 来定制exector来设置线程的属性:

public class DaemonThreadPoolExecutor extends ThreadPoolExecutor {

	public DaemonThreadPoolExecutor() {
		super(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new DaemonThreadFactory());//其实这里参数除了ThreadFactory 都是CachedThreadPool的参数配置
		/**
		 * 构造方法中各个参数的意义: 
		 * corePoolSize: 线程池维护线程的最少数量
		 * 
		 * maximumPoolSize:线程池维护线程的最大数量
		 * 
		 * keepAliveTime: 线程池维护线程所允许的空闲时间
		 * 
		 * unit: 线程池维护线程所允许的空闲时间的单位
		 * 
		 * workQueue: 线程池所使用的缓冲队列
		 * 
		 * handler: 线程池对拒绝任务的处理策略
		 */
	}

	public static void main(String[] args) throws Exception {
		ExecutorService exec = new DaemonThreadPoolExecutor();
		for (int i = 0; i < 5; i++) {
			exec.execute(new DaemonFromFactory());
		}
		System.out.println("all daemon run");
		TimeUnit.MILLISECONDS.sleep(1200);
	}
}

ThreadPoolExecutor 介绍:http://blog.csdn.net/wangwenhui11/article/details/6760474
SynchronousQueue 介绍:http://ifeve.com/java-synchronousqueue/

可以通过isDaemon() 来判断一个线程是否是后台线程,一个后台线程创建的线程也是后台线程。
后台线程可以在不执行finally的情况下就终止其线程

public class ADaemon implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			System.out.println("a daemon is runing");
			TimeUnit.MILLISECONDS.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			System.out.println("finally block exec?");
		}
	}
	public static void main(String[] args) throws Exception {
		Thread t=new Thread(new ADaemon());
		t.setDaemon(true);
		t.start();
	}
}
//output
//a daemon is runing  有可能在后台线程还没有运行起来主线程就结束了,所以可能什么都不输出,多运行几次能看到这个输出结果

因此不能优雅的关闭后台线程,后台线程结束也没有任何确认形式

原文地址:https://www.cnblogs.com/joeCqupt/p/6814665.html