最近在看并发操作时候,例如jmeter进行接口压测(本地自己的springboot2的环境),发现一个有趣的现象,就是关于线程http-nio-8080-exec-1,http-nio-8080-exec-2等等的出现。但是这个线程数不管我的压测数是多少这个线程数不会超过10.抱着好奇的心去搜索了一下相关的文章,但是没有看到比较合适的。然后就只有自己去跟了一下源码。在此自己总结一下。
两个问题:
1、这个http-nio-8080-exec东西是怎么来的
2、为什么这个线程数不超过10
把这两个问题其实可以一起归为一个问题来跟代码进行解决:
因为我们知道,一般在自定义线程或者线程池名称的时候,我们是可以自己去设置相关的线程名字的。这个名称的来源就是如下:
在请求线程经过Tomcat时,会进入到org.apache.coyote.AbstractProtocol,这个方法,这是一个抽象类,可以看出其实这里就是在进行一个名称和端口号的拼接操作。getNamePrefix()的具体实现是在org.apache.coyote.http11.Http11NioProtocol
private String getNameInternal() {
StringBuilder name = new StringBuilder(getNamePrefix());
name.append('-');
if (getAddress() != null) {
name.append(getAddress().getHostAddress());
name.append('-');
}
int port = getPortWithOffset();
if (port == 0) {
// Auto binding is in use. Check if port is known
name.append("auto-");
name.append(getNameIndex());
port = getLocalPort();
if (port != -1) {
name.append('-');
name.append(port);
}
} else {
name.append(port);
}
return name.toString();
}
@Override
protected String getNamePrefix() {
if (isSSLEnabled()) {
return "https-" + getSslImplementationShortName()+ "-nio";
} else {
return "http-nio";
}
}
当创建连接的时候回进入到org.apache.tomcat.util.net.AbstractEndpoint,进入start()方法
public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bindWithCleanup();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
然后是startInternal(),在这个方法有一段
if (getExecutor() == null) { createExecutor(); }。也就是说,如果这个是一个新连接的话,会去新建一个线程。createExecutor()这个方法很重要算是核心实现了。
public void createExecutor() {
internalExecutor = true;
TaskQueue taskqueue = new TaskQueue();
TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
taskqueue.setParent( (ThreadPoolExecutor) executor);
}
从这里可以看到,这个创建连接的过程,就是通过网一个队列进行添加。这个getName()方法就是刚刚上面返回的http-nio-8080的那一部分。
这里可以看到构造一个TaskThreadFactory类。构造方法如下
public TaskThreadFactory(String namePrefix, boolean daemon, int priority) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
this.namePrefix = namePrefix;
this.daemon = daemon;
this.threadPriority = priority;
}
重点看这个group,他是属于java.lang.ThreadGroup。构造方法中有这样一段代码
private ThreadGroup() { // called from C code
this.name = "system";
this.maxPriority = Thread.MAX_PRIORITY;
this.parent = null;
}
Thread.MAX_PRIORITY=10;换言之,就是在通过Tomcat的形式建立连接的时候,新建的连接对象都会有用到ThreadGroup,在ThreadGroup中就有限制最大的数卫10.所以会出现http-nio-8080-exec-9的情况也很正常了。
转载请注明:关于springboot访问tomcat,线程http-nio-8080-exec的来源问题 | 胖虎的工具箱-编程导航