看JAVA编程思想时候感觉作者有句话不对(关于并发)
中文第四版的哦(p657倒数第十行)“然后在它回收旧线程时停止创建新线程”。
这个它指的是CachedThreadPool,我一开始是深信不疑的,认为CachedThreadPool如果一个线程死亡了,那它就不会再创建新的线程了。后来看到一个大牛说“会”。于是自己做了实验:
package test;import java.util.*;import java.util.concurrent.*;import java.util.concurrent.locks.*;import java.io.*;public class Test1 implements Callable<Thread>{static ThreadLocal<Integer> t=new ThreadLocal<Integer>(){@Overrideprotected synchronized Integer initialValue(){return new Integer(0);}};static int count=0;final int id=count++;public Test1(){System.out.println("Constructor:"+id);}static class Test2 implements Runnable{public void run(){System.out.println(t.get()+" o");}}public Thread call(){t.set(id);System.out.println(t.get());return Thread.currentThread();}public static void main(String[] args){ExecutorService exec=Executors.newCachedThreadPool();for (int i=0;i<4;i++)exec.submit(new Test1());Future<Thread> f=exec.submit(new Test1());try{((Thread)f.get()).join();}//等待线程死亡catch (Exception e){}for (int i=0;i<5;i++)exec.execute(new Test2());exec.shutdownNow();}}
结果如下:
Constructor:0
Constructor:1
Constructor:2
Constructor:3
Constructor:4
1
3
0
2
4
0 o
0 o
0 o
0 o
0 o
我是用ThreadLocal来确定一个线程的存活的(因为ExecutorService没有提供关于线程池里线程信息的方法只好这么做了,如果大家有什么其他方法的话也不吝赐教)这里虽然只是join了一个线程,但是从结果看其他线程也都死亡了。ThreadLocal是与线程相关的变量,线程换了一个任务以后也仍然保持原值。不信的话,可以把join方法那句去掉。
Constructor:1Constructor:2Constructor:3Constructor:4Constructor:5Constructor:6152436Constructor:7Constructor:878Constructor:9Constructor:10910Constructor:111111 o3 o2 o4 o9 o
老线程都用上了,这也就是它的优势吧,但是这个pool会在所有线程都没事干的时候死光光,如果主线程不轮询的话,主线程结束,所以子线程也已经结束了,程序就停止了。fixed的就不会这样了。我猜大部分应该都会轮询吧。