1. 问题发现

某次网页打不开,开始进行分析。查看系统对应的Tomcat应用进程存在,Tomcat的HTTP端口有在监听,怀疑是Tomcat某个处理HTTP服务的线程出现问题。

根据客户端IP定位到对应的服务器实例,与其他能够正常访问的服务器的线程相比,发现少了部分线程:http-nio-xxx-Acceptor-0、http-nio-xxx-AsyncTimeout、http-nio-xxx-ClientPoller-0、http-nio-xxx-ClientPoller-1等。

重启Tomcat进程后,HTTP服务恢复正常。

使用“Acceptor”关键字在catalina.out日志文件中搜索,找到“Exception in thread “http-nio-xxx-Acceptor-0””,在附近可以看到“java.lang.OutOfMemoryError: Java heap space”,可知问题原因是上述线程因为OOM被异常终止,导致Tomcat无法再提供HTTP服务。

以下分析的Tomcat版本为8.5.63。

2. Tomcat connector分析

2.1. connector配置分析

参考Tomcat文档“Apache Tomcat 8 Configuration Reference”( http://tomcat.apache.org/tomcat-8.5-doc/config/index.html )。

conf/server.xml文件中的配置指令可以配置Tomcat Servlet/JSP容器的行为。

Connectors元素用于表示外部客户端向特定服务(Service)发送请求(及接收响应)之间的接口。

参考Tomcat文档“The HTTP Connector”( http://tomcat.apache.org/tomcat-8.5-doc/config/http.html )。

HTTP Connector元素表示支持HTTP/1.1协议的Connector组件。Connector组件实例监听服务器指定TCP端口号上的连接。一个或多个Connector可以被配置为单个Service的一部分,每个Connector都转发到关联的Engine,来进行请求处理,及创建响应。

2.1.1. connector protocol属性

connector的所有实现都支持protocol属性,指定用于处理接入流量的协议。默认值为“HTTP/1.1”,使用自动切换机制,选择基于Java NIO的connector,或基于APR/native的connector。

若Windows环境的PATH或大多数Unix系统的LD_LIBRARY_PATH环境变量对应目录中包含了Tomcat本机库,且用于初始化APR的AprLifecycleListener的useAprConnector属性设置为true,则APR/native connector会被使用。

为了使用显式指定的协议,而不是依赖上述自动切换机制,protocol属性可以使用以下参数:

参数值 说明
org.apache.coyote.http11.Http11NioProtocol 使用非阻塞Java NIO connector
org.apache.coyote.http11.Http11Nio2Protocol 使用非阻塞Java NIO2 connector
org.apache.coyote.http11.Http11AprProtocol 使用APR/native connector

以上不同connector之间的对比,可以参考 http://tomcat.apache.org/tomcat-8.5-doc/config/http.html#Connector_Comparison 。

2.1.1.1. Tomcat 8.5版本前后支持的connector协议变化

参考 http://tomcat.apache.org/tomcat-8.0-doc/config/http.html#Connector_Comparison ,在Tomcat 8.5.x之前的8.0.x版本中,Connector元素的protocol属性还支持配置为“org.apache.coyote.http11.Http11Protocol”,即阻塞Java connector(bio)。

从Tomcat 8.5.x版本开始,不再支持使用org.apache.coyote.http11.Http11Protocol作为Connector协议实现类。

2.1.1.2. APR connector说明

参考 http://tomcat.apache.org/tomcat-8.5-doc/apr.html#Introduction 。

Tomcat可以使用Apache Portable Runtime(APR)提供更好的可伸缩性,更高性能以及与本机服务更好集成的技术。Apache Portable Runtime是一个高度可移植的库,是Apache HTTP Server 2.x的核心。APR有很多作用,包括访问高级IO功能,操作系统级别功能和本机进程处理。

2.1.1.3. Windows环境APR connector安装

启用APR支持主要需要安装以下本机组件:

  • APR库;
  • Tomcat使用的APR的JNI包装器(libtcnative);
  • OpenSSL库。

为Windows环境提供的二进制文件为tcnative-1.dll,是一个静态编译的dll文件,包含了OpenSSL与APR。可从以下地址下载32位或64位操作系统使用的二进制文件: https://tomcat.apache.org/download-native.cgi 。

2.1.2. connector acceptorThreadCount属性

标准HTTP Connector(NIO, NIO2,APR/native)都支持acceptorThreadCount属性,指定用于接受连接的线程数。默认值为1,通常不需要设置为超过2的值。

2.1.3. connector pollerThreadCount属性

NIO Connector(不包括NIO2 Connector)支持pollerThreadCount属性,指定处理轮询(polling)事件的线程数量,默认值为每个处理器1个线程,但最终数量不会超过2个。

2.2. 配置connector使用不同的协议

在Tomcat的conf/server.xml配置文件的<Server><Service>节点中,可通过类似以下配置,指定Connector使用不同的协议,分别监听不同的端口:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol"/>
<Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" />
<Connector port="8082" protocol="org.apache.coyote.http11.Http11Nio2Protocol" />
<Connector port="8083" protocol="org.apache.coyote.http11.Http11AprProtocol" />

2.2.1. APR Connector配置说明

在Windows环境配置Tomcat使用APR Connector时,若本机不存在APR组件文件,则Tomcat不会监听对应的端口,需要确保APR组件文件在本机存在,才能使用APR Connector。

从 https://archive.apache.org/dist/tomcat/tomcat-8/ 下载Tomcat 8.x版本压缩包时,选择apache-tomcat-xxx-windows-xx.zip之外的压缩包,其中可能没有包含Windows环境Tomcat APR使用的DDL文件tcnative-1.dll。在这种情况下,需要从 https://tomcat.apache.org/download-native.cgi 下载APR组件的压缩包,可选择“Native 1.2.26 Windows Binaries zip (recommended)”,下载后将bin\x64\tcnative-1.dll文件解压到Tomcat的bin目录,Tomcat才能使用APR。

2.3. connector不同协议的相关线程

使用jstack或jconsole命令查看Tomcat进程中Connector相关的线程。

使用Http11Protocol作为协议类的Connector相关的线程如下:

http-nio-8080-AsyncTimeout
http-nio-8080-Acceptor-0
http-nio-8080-ClientPoller-1
http-nio-8080-ClientPoller-0
http-nio-8080-exec-xxx

使用Http11NioProtocol作为协议类的Connector相关的线程如下:

http-nio-8081-AsyncTimeout
http-nio-8081-Acceptor-0
http-nio-8081-ClientPoller-1
http-nio-8081-ClientPoller-0
http-nio-8081-exec-xxx

使用Http11Nio2Protocol作为协议类的Connector相关的线程如下:

http-nio2-8082-AsyncTimeout
http-nio2-8082-Acceptor-0
http-nio2-8082-exec-xxx

使用Http11AprProtocol作为协议类的Connector相关的线程如下:

http-apr-8083-AsyncTimeout
http-apr-8083-Acceptor-0
http-apr-8083-Sendfile
http-apr-8083-Poller
http-apr-8083-exec-xxx

以上Connector均有Acceptor线程,数量均为1,由上述acceptorThreadCount属性决定。

使用Http11Protocol作为协议类的Connector,未使用bio,而是使用nio。

NIO Connector的ClientPoller线程数量为2,由上述pollerThreadCount属性决定。

NIO2 Connector没有ClientPoller线程。

2.4. connector协议类分析

Tomcat HTTP Connector的协议类均继承自AbstractHttp11Protocol、AbstractProtocol,如下所示:

Object (java.lang)AbstractProtocol (org.apache.coyote)AbstractHttp11Protocol (org.apache.coyote.http11)AbstractHttp11JsseProtocol (org.apache.coyote.http11)Http11NioProtocol (org.apache.coyote.http11)Http11Protocol (org.apache.coyote.http11)Http11Nio2Protocol (org.apache.coyote.http11)Http11AprProtocol (org.apache.coyote.http11)

Http11Protocol类已被标记为@Deprecated,继承自Http11NioProtocol类,且没有进行其他处理,因此使用Http11Protocol类作为Connector的协议类与使用Http11NioProtocol类的效果相同。

在Tomcat 8.5.x之前的8.0.x版本中,Http11Protocol类没有继承自Http11NioProtocol类,能够作为BIO Connector使用。

3. Tomcat Acceptor线程分析

3.1. Tomcat创建Acceptor线程代码分析

org.apache.coyote.AbstractProtocol类中使用了Connector的acceptorThreadCount属性,该类在tomcat-coyote.jar中,get/setAcceptorThreadCount()方法调用了AbstractEndpoint类型endpoint对象的get/setAcceptorThreadCount()方法。

org.apache.tomcat.util.net.AbstractEndpoint类中定义了成员变量acceptorThreadCount,默认值为1。

AbstractEndpoint类的startAcceptorThreads()方法用于创建Acceptor线程,线程名称为当前对象的getName()方法返回值,加上“-Acceptor-”,以及当前创建的线程序号。

AbstractEndpoint类的getName()方法返回成员变量name的值,在setName()方法中进行设置。

在AbstractProtocol类的init()方法中,调用getName()方法,该方法会调用getNameInternal()方法,并对返回值调用ObjectName.quote(),使返回的字符串首尾被半角双引号包含。getNameInternal()方法中返回的字符串以getNamePrefix()方法返回值开头,getNamePrefix()方法为抽象方法。

之后调用AbstractEndpoint对象的setName()方法,设置的字符串为AbstractProtocol对象的getName()方法返回值去掉首尾各一个字符后的字符串。

即AbstractEndpoint类的startAcceptorThreads()方法中创建的Acceptor线程名称,以AbstractProtocol类子类的getNamePrefix()方法返回值开头。

当Connector使用HTTP协议时,AbstractProtocol类相关子类的getNamePrefix()方法返回值如下(使用HTTPS协议时不同):

子类 getNamePrefix()方法返回值
Http11Protocol http-nio
Http11NioProtocol http-nio
Http11Nio2Protocol http-nio2
Http11AprProtocol http-apr

以上代码中的线程名称前缀与Tomcat进程实际的线程名称相符。

在Tomcat 8.5.x之前的8.0.x版本中,Http11Protocol类的getNamePrefix()方法返回值为“http-bio”。

3.2. accept连接最大数量限制相关代码

对连接进行accept时最大数量限制相关代码,可参考 https://blog.csdn.net/a82514921/article/details/115359671 。

3.3. 结束Tomcat Acceptor线程的方法

为了结束Tomcat进程中指定HTTP Connector对应的Acceptor线程,可以在Java代码中获得对应线程的Thread对象后,调用其stop()方法将其结束。

将以下代码保存为对应Tomcat进程某个应用web目录中的.jsp文件,通过浏览器访问上述jsp文件对应URL后,可将HTTP Connector所有相关的Acceptor线程结束(等待一段时间后对应线程会结束)。

<%@ page import="java.lang.*"%><%String threadName= Thread.currentThread().getName();System.out.println("current thread name: " + threadName);ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();ThreadGroup topGroup = threadGroup;while (threadGroup != null) {topGroup = threadGroup;threadGroup = threadGroup.getParent();}int slackSize = topGroup.activeCount() * 2;Thread[] slackThreads = new Thread[slackSize];topGroup.enumerate(slackThreads);boolean find = false;for (Thread thread : slackThreads) {if (thread == null) {continue;}if (thread.getName().contains("http-") && thread.getName().contains("-Acceptor-")) {System.out.println("kill Acceptor thread name: " + thread.getName());find = true;thread.stop();}}out.print(threadName + " find: " + find);
%>

4. Tomcat Acceptor线程终止后对客户端的影响

Tomcat Acceptor线程终止后对客户端的影响如下:

假如客户端未设置从服务器读取返回的超时时间,则客户端会等待Tomcat返回数据,但由于Tomcat Acceptor线程已终止,无法再向客户端返回数据,因此客户端会一直阻塞等待服务器返回,且连接不会被Tomcat终止。

假如客户端有设置从服务器读取返回的超时时间,则客户端会等待Tomcat返回数据,达到超时时间后自动断开连接,不再等待服务器返回。

使用上述方法可以结束Tomcat进程中HTTP Connector对应的全部Acceptor线程,之后可以分析Acceptor线程终止后对客户端的影响。

4.1. 网络连接分析

Tomcat Acceptor线程终止后,在安装Tomcat的Linux服务器机器分析,当客户端连接上服务器Tomcat对应端口后,在服务器使用netstat命令查看连接情况,有客户端建立的状态为ESTABLISHED的连接。

当客户端(Windows或Linux环境)断开连接并结束对应进程之后,在服务器查看连接情况,有客户端建立的状态为CLOSE_WAIT的连接,一直存在,未自动消失。

4.2. 抓包分析

Tomcat Acceptor线程终止后,在服务器及客户端对网络流量抓包分析,与能够正常访问Tomcat时对比,可以发现服务器没有向客户端返回HTTP响应数据包。

4.3. 使用Chrome浏览器访问

Tomcat Acceptor线程终止后,使用Windows环境的Chrome浏览器打开Tomcat的任意URL,Chrome会一直处于加载中状态,无法显示页面。

4.4. 使用telnet命令访问

Tomcat正常运行时,使用Windows或Linux环境的telnet命令访问Tomcat的端口,能够连接成功,输入任意非回车字符后,再输入回车,Tomcat会返回数据并终止连接,在客户端执行telnet的控制台能够看到Tomcat返回的HTTP协议数据。

Tomcat Acceptor线程终止后,使用telnet命令访问Tomcat的端口,能够连接成功,无论输入什么内容,Tomcat都不会返回数据,连接也不会终止。

4.5. 使用curl命令访问

4.5.1. 未指定–max-time

Tomcat Acceptor线程终止后,在Linux环境使用curl命令访问Tomcat的任意URL,curl命令会一直等待Tomcat返回,不会自动结束,如下所示:

curl -v http://127.0.0.1:8080
* About to connect() to 127.0.0.1 port 8080 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8080
> Accept: */*
>

在执行curl命令时,通过“–connect-timeout n”参数指定连接超时时间(单位为秒),curl命令也会一直等待,因为“–connect-timeout”参数无法设置从服务器读取返回的超时时间。

4.5.2. 有指定–max-time

在执行curl命令时,可以通过“–max-time n”参数指定整个操作的超时时间(单位为秒),当超过指定时间后,若操作未结束,则curl命令会自动结束并断开连接,如下所示:

curl -v --max-time 5 http://127.0.0.1:8080
* About to connect() to 127.0.0.1 port 8080 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8080
> Accept: */*
>
* Operation timed out after 5000 milliseconds with 0 out of -1 bytes received
* Closing connection 0

4.6. 使用Java Socket类访问

4.6.1. 未指定SocketOptions.SO_TIMEOUT超时时间

Tomcat Acceptor线程终止后,使用Java Socket类访问Tomcat的端口,若未指定SocketOptions.SO_TIMEOUT超时时间,则客户端Java程序会一直等待Tomcat返回。

此时查看对应的线程状态为RUNNABLE,调用堆栈如下所示,可以看到线程在等待SocketInputStream.socketRead0()方法执行完毕:

java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
java.net.SocketInputStream.read(SocketInputStream.java:171)
java.net.SocketInputStream.read(SocketInputStream.java:141)

执行Socket类的connect(SocketAddress endpoint, int timeout)方法时,可以通过timeout参数指定连接超时,客户端Java程序仍然会一直等待Tomcat返回,因为该参数只能设置连接服务器的超时时间,但无法设置从服务器读取返回的超时时间。

4.6.2. 有指定SocketOptions.SO_TIMEOUT超时时间

使用Java Socket类访问Tomcat的端口,可以通过Socket类的setSoTimeout(int timeout)方法指定SocketOptions.SO_TIMEOUT超时时间,可以设置当前Socket对象关联的InputStream对象的read()操作被阻塞的时间,当超时后,会出现java.net.SocketTimeoutException异常。示例如下:

Socket socket = new Socket();
socket.setSoTimeout(5000);
socket.connect(new InetSocketAddress("127.0.0.1", 8080), 1000);

客户端Java程序在读取服务器返回数据时,当等待时间超过setSoTimeout()方法指定的毫秒数时,会出现java.net.SocketTimeoutException异常,如下所示:

java.net.SocketTimeoutException: Read timed outat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)at java.net.SocketInputStream.read(SocketInputStream.java:171)at java.net.SocketInputStream.read(SocketInputStream.java:141)

因此使用Java Socket类访问服务器时,一定要设置合理的SocketOptions.SO_TIMEOUT超时时间,否则可能导致客户端Java程序中的线程都被阻塞。

4.7. 使用Java HttpClient访问

以下使用的HttpClient版本为4.x。

4.7.1. 未指定socketTimeout超时时间

Tomcat Acceptor线程终止后,使用Java HttpClient访问Tomcat对应端口的任意URL,在创建RequestConfig对象时若未指定socketTimeout超时时间,则客户端Java程序会一直等待Tomcat返回。

此时查看对应的线程状态为RUNNABLE,调用堆栈如下所示,可以看到线程在等待SocketInputStream.socketRead0()执行结束:

java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
java.net.SocketInputStream.read(SocketInputStream.java:171)
java.net.SocketInputStream.read(SocketInputStream.java:141)
org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:136)
org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:152)
org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:270)
org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:260)
org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:161)
org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:153)
org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:271)
org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:254)
org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)

HttpClient可以配置以下超时时间:

connectionRequestTimeout,用于指定从连接管理器中获取连接时的超时时间;

connectTimeout,用于指定连接建立的超时时间。

以上超时时间无法指定从服务器读取返回时的阻塞等待时间。

4.7.2. 有指定socketTimeout超时时间

参考 https://hc.apache.org/httpcomponents-client-4.5.x/current/httpclient/apidocs/org/apache/http/client/config/RequestConfig.html ,getSocketTimeout()方法返回以毫秒为单位的Socket超时时间(SO_TIMEOUT)。

查看HttpClient的代码,在org.apache.http.HttpConnection接口的实现类的setSocketTimeout()方法中,会调用Socket类的setSoTimeout()方法。

使用Java HttpClient访问Tomcat对应端口的任意URL,在创建RequestConfig对象时,可以通过RequestConfig.Builder类的setSocketTimeout()方法指定socketTimeout超时时间,即指定Socket的SocketOptions.SO_TIMEOUT超时时间。

客户端Java程序在读取服务器返回数据时,当等待时间超过setSocketTimeout()方法指定的毫秒数时,会出现java.net.SocketTimeoutException异常,如下所示:

java.net.SocketTimeoutException: Read timed outat java.net.SocketInputStream.socketRead0(Native Method) ~[?:1.8.0_144]at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[?:1.8.0_144]at java.net.SocketInputStream.read(SocketInputStream.java:171) ~[?:1.8.0_144]at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[?:1.8.0_144]at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:136) ~[httpcore-4.3.3.jar:4.3.3]...

因此使用Java HttpClient访问服务器时,一定要RequestConfig.Builder类的setSocketTimeout()方法设置合理的超时时间,原因同上。

5. 使用Java程序模拟Acceptor线程终止的场景

使用Java程序可以模拟Acceptor线程终止的场景,可参考 https://blog.csdn.net/a82514921/article/details/115359671 。

6. Tomcat Connector其他线程终止后对客户端的影响

6.1. NIO ClientPoller线程终止后对客户端的影响

当Tomcat NIO Connector的一个ClientPoller线程终止后(Acceptor线程正常运行),由于ClientPoller线程存在两个(多CPU的机器),与被终止的ClientPoller线程相关的客户端访问会受到影响,现象与Acceptor线程被终止时相同;与被终止的ClientPoller线程无关的客户端访问正常。

7. 监控Tomcat处理HTTP请求线程是否正常

为了监控Tomcat运行是否正常,除了需要监控Tomcat进程是否启动,端口是否监听外,还需要监控处理HTTP请求的线程是否正常,可以通过curl或其他工具定时访问Tomcat中的静态页面,或不需要登录鉴权的请求。

使用curl命令监控时,需要通过–max-time参数指定合适的超时时间;使用其他工具时,也需要指定合适的超时时间,避免当Tomcat无法正常处理HTTP请求时监控工具被阻塞。

Tomcat因Acceptor线程终止无法访问分析相关推荐

  1. 多方面,全访问的剖析Tomcat十大线程和四大通道

    tomcat服务器在JavaEE项目中使用率非常高,所以在生产环境对tomcat的优化也变得非常重要了. 本专题课在调优压测时我们选择tomcat9,那我们为什么选择9版本呢?因为9的性能更高,更稳定 ...

  2. Tomcat运行一段时间后访问变慢分析历程

    主要查看三方面: 查看程序中的Session是否定时清空了 查看mysql是否有没有close的连接 查看Tomcat的内存设置,根据下列设置 环境运行一天或者几天,网站访问就很卡,手机端app访问页 ...

  3. 通过 Java 线程堆栈进行性能瓶颈分析

    改善性能意味着用更少的资源做更多的事情.为了利用并发来提高系统性能,我们需要更有效的利用现有的处理器资源,这意味着我们期望使 CPU 尽可能出于忙碌状态(当然,并不是让 CPU 周期出于应付无用计算, ...

  4. tomcat关闭后线程依然运行解决办法

    tomcat关闭后线程依然运行解决办法,设置线程为守护线程 守护线程与非守护线程 最近在看多线程的Timer章节,发现运用到了守护线程,感觉Java的基础知识还是需要补充. Java分为两种线程:用户 ...

  5. synchronized原理_Java并发编程—synchronized保证线程安全的原理分析

    前言 程安全是并发编程中的重要关注点,应该注意到的是,造成线程安全问题的主要诱因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据.因此为了解决这个问题,我们可能需要这样一个方 ...

  6. Java多线程:线程8锁案例分析

    线程8锁案例分析 通过分析代码,推测打印结果,并运行代码进行验证 1.两个线程调用同一个对象的两个同步方法 被synchronized修饰的方法,锁的对象是方法的调用者.因为两个方法的调用者是同一个, ...

  7. linux c 线程的创建、线程等待、线程终止、线程分离

    1. 什么是线程   线程是进程执行内部的一个执行分支,在一个进程内部运行的多种执行流:内部本质上是多个线程在同一个地址空间运行:第一个pcb称之为主线程:有多个线程就有多个执行流:一个进程至少有一个 ...

  8. Tomcat中的线程池(APR和ThreadPool)

    一.容器简化了程序员自身的多线程编程. 各种Web容器,如Tomcat,Resion,Jetty等都有自己的线程池(可在配置文件中配置),所以在客户端进行请求调用的时候,程序员不用针对Client的每 ...

  9. kafka 启动_深入理解Kafka服务端之Acceptor线程是如何启动和工作的

    一.场景分析上一篇讲到了Kafka网络通信采用了Java NIO的主从Reactor多线程模型,而Acceptor就是Kafka网络通信中很重要的一个线程对象.它通过selector接收客户端的连接请 ...

最新文章

  1. WinForm UI设计与开发思路(转)
  2. 大学python教材思维导图_Python核心知识体系的14张思维导图
  3. 电子邮件一般不在用户计算机中,[单选] 在一个完整的Internet电子邮件地址中,决定用户信箱所在的计算机地址的是()。...
  4. OpenShift 4 - Knative教程 (5) Eventing之Source和Sink
  5. ecshop实现弹出登录框
  6. sqlite or svn 错误 The database disk image is malformed 可解决
  7. Python基于OpenCV实现视频数据切割为图像数据
  8. 【肌电信号】肌电信号处理系统含Matlab源码
  9. Unity预览代码中文乱码解决方案
  10. 一键怎样批量修改图片像素大小
  11. python怎么回到开头_python如何回到cod的开始
  12. java医疗报销_医疗保险报销流程图(修改后)
  13. Cross Domain Person Re-Identification With Large Scale Attribute Annotated Datasets参考文献解读
  14. 阿里大佬自述:Java零基础到精通是这样炼成的!
  15. 服务器远程注销,命令行注销windows远程登录账户
  16. 价值 20 万美元的爱马仕包包是用蘑菇做的,你还会买吗?
  17. 数据库Date数据与字符串如何转换
  18. 电脑桌面计算机怎么设置,示例win7电脑桌面图片怎么设置
  19. Tbase 源码 (四)
  20. shred 粉碎文件

热门文章

  1. CTF密码学题目初探
  2. 计算机组成原理中译码器,计算机组成原理课程设计-指令系统及七段译码器设计.doc...
  3. ThinkPHP 3.2.3 使用 PHPExcel 处理 Excel 表格
  4. linux ntp时间源服务器,NTP时间服务器
  5. CMOS单刀单掷开关(SPST)笔记
  6. python1加到100_python实现1加到100
  7. 大一科技界做的LED装饰灯
  8. 74ls164驱动数码管(共阳)
  9. c语言程序设计成绩管理应用书,C语言程序设计学生成绩管理系统实验报告
  10. Painter X Artists(艺术家)画