使用线程池的时候我们一定都会自定义线程池,而线程池有一个参数是 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线程明明没有设置,为什么里边就有数据呢。 它的数据哪里来的呢。这里就是线程池的扩大。