使用线程池的时候我们一定都会自定义线程池,而线程池有一个参数是 ThreadFactory, 它的工作就是生产线程。(设置线程池的目的则是为了在jstack的时候看到这个线程在做什么)
public interface ThreadFactory {/*** Constructs a new {@code Thread}. Implementations may also initialize* priority, name, daemon status, {@code ThreadGroup}, etc.** @param r a runnable to be executed by new thread instance* @return constructed thread, or {@code null} if the request to* create a thread is rejected*/Thread newThread(Runnable r);}
线程池在创建代码的时候,也离不开 Thread 的实例化和初始化的过程,而线程初始化又会涉及到 ThreadLocal 的传递。
private Thread(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {if (inheritThreadLocals && parent.inheritableThreadLocals != null)this.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);}
从这里可以看到,ThreadLocal的配置不会传递到子线程,而inheritableThreadLocals会传递到子线程,这里的子线程的含义不仅包括了new 出来的thread,同时也包括线程池产生的thread。
这里就会涉及到一个问题,当父线程中的 inheritableThreadLocals有数据的时候,子线程是可以获取到的,这里如果辨别不当,就会有哎,都还没设置呢,怎么子线程就有数据了呢的误区。 其实是 inheritableThreadLocals 在这里发生了重要作用。
单独把这一块拿出来说可能大家都不陌生,但是如果把线程池的含义扩大化,扩大的Tomcat,扩大到jetty里边,然后再来看这个过程就不是那么容易了。
例如项目初始化的时候,Tomcat使用main线程设置了一个数据,然后tomcat线程明明没有设置,为什么里边就有数据呢。 它的数据哪里来的呢。这里就是线程池的扩大。
