让步
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 有可能在后台线程还没有运行起来主线程就结束了,所以可能什么都不输出,多运行几次能看到这个输出结果
因此不能优雅的关闭后台线程,后台线程结束也没有任何确认形式