第七章:实现多线程支持-Minitomcat
第七章:实现多线程支持
在本章中,我们将为 MiniTomcat 引入多线程支持,旨在显著提升服务器的并发处理能力。通过引入线程池(Thread Pool)机制,服务器能够同时处理多个客户端请求,避免单线程模型下的请求阻塞问题。这将使服务器在面对高并发场景时更加高效,更好地支持多用户同时访问。
7.1 功能目标
本章的核心改造目标如下:
- 多线程支持:利用线程池管理线程资源,为每个客户端请求分配独立的线程进行处理。
- 线程池机制:避免为每个请求频繁创建和销毁线程,通过复用线程降低系统开销,提高执行效率。
- 并发处理:支持多个客户端同时访问不同的 Servlet,确保请求之间互不干扰,实现真正的并发处理。
7.2 代码结构
本次修改将引入线程池机制,主要通过 ExecutorService 来管理工作线程。项目代码结构更新如下:
MiniTomcat
├─ src
│ ├─ main
│ │ ├─ java
│ │ │ ├─ com.daicy.minitomcat
│ │ │ │ ├─ servlet
│ │ │ │ │ ├─ CustomServletOutputStream.java // 自定义的 Servlet 输出流类
│ │ │ │ │ ├─ CustomHttpSession.java // 自定义的 HttpSession
│ │ │ │ │ ├─ HttpServletRequestImpl.java // HTTP 请求的实现类
│ │ │ │ │ ├─ HttpServletResponseImpl.java // HTTP 响应的实现类
│ │ │ │ │ ├─ ServletConfigImpl.java // Servlet 配置的实现类
│ │ │ │ │ ├─ ServletContextImpl.java // Servlet 上下文的实现类
│ │ │ │ ├─ CounterServlet.java // Session 功能 Servlet 示例类
│ │ │ │ ├─ HelloServlet.java // Servlet 示例类
│ │ │ │ ├─ HttpConnector.java // 连接器类
│ │ │ │ ├─ HttpProcessor.java // 请求处理器
│ │ │ │ ├─ HttpServer.java // 主服务器类
│ │ │ │ ├─ HttpRequestParser.java // HttpRequest 信息解析类
│ │ │ │ ├─ ServletLoader.java // Servlet 加载器
│ │ │ │ ├─ ServletProcessor.java // Servlet 处理器
│ │ │ │ ├─ StaticResourceProcessor.java // 静态资源处理器
│ │ │ │ ├─ SessionManager.java // Session 管理器
│ │ │ │ ├─ ThreadPool.java // 线程池管理
│ │ │ │ ├─ WebXmlServletContainer.java // Servlet 容器相关类
│ │ ├─ resources
│ │ │ ├─ webroot
│ │ │ │ ├─ index.html
│ │ │ ├─ web.xml
│ ├─ test
├─ pom.xml7.3 代码实现
7.3.1 创建 ThreadPool 类
我们将基于 Java 并发包中的 ThreadPoolExecutor 来实现线程池管理。ThreadPool 类负责封装线程池的生命周期,并提供提交任务的接口。
package com.daicy.minitomcat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class ThreadPool {
private ExecutorService executor;
public ThreadPool(int poolSize) {
// 创建固定大小的线程池
executor = Executors.newFixedThreadPool(poolSize);
}
public void submitTask(Runnable task) {
executor.submit(task);
}
public void shutdown() {
if (executor != null) {
executor.shutdown();
}
}
public boolean isShutdown() {
return executor.isShutdown();
}
public ThreadPoolExecutor getExecutor() {
return (ThreadPoolExecutor) executor;
}
}7.3.2 修改 HttpProcessor 类以支持多线程
HttpProcessor 类将实现 Runnable 接口,以便能够作为任务提交给线程池。每个客户端请求将由线程池中的一个独立线程来处理,从而避免阻塞主线程。
public class HttpProcessor implements Runnable {
private Socket socket;
private final static ServletProcessor servletProcessor = new ServletProcessor();
private final static StaticResourceProcessor staticProcessor = new StaticResourceProcessor();
public HttpProcessor(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
// 处理请求并返回响应
process();
}
// ...... 其他代码保持不变
}7.3.3 修改 HttpConnector 类以启动线程池
HttpConnector 类负责启动服务器监听端口,并利用初始化好的线程池来处理客户端连接请求。
package com.daicy.minitomcat;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpConnector implements Runnable {
private static final int PORT = 8080;
// 创建一个线程池,最多支持 10 个并发请求
private static ThreadPool threadPool = new ThreadPool(10);
public void start() {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("HTTP Connector is running on port " + PORT);
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("Accepted connection from " + clientSocket.getInetAddress());
// 将连接交给 HttpProcessor 处理,并提交给线程池
HttpProcessor processor = new HttpProcessor(clientSocket);
threadPool.submitTask(processor);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}7.4 测试
完成代码修改后,请按以下步骤验证多线程支持是否生效:
- 启动服务器:运行主程序,确保服务器正常启动且无报错。
- 并发访问:使用多个浏览器标签页或不同的 HTTP 客户端工具,同时访问不同的路径(如静态资源与 Servlet 接口)。
- 观察日志:检查控制台日志,确认多个请求被同时接收和处理,且没有出现请求阻塞或排队等待的现象。
- 性能验证:观察服务器的响应时间,确保在高并发下线程池有效提升了吞吐能力。
7.5 学习收获
通过本章的实现,我们获得了以下技术经验:
- 线程池应用:掌握了线程池的核心概念,学会了如何使用
ExecutorService和ThreadPoolExecutor管理线程,避免频繁创建销毁线程带来的性能开销。 - 多线程编程:深入理解了如何在 Web 服务器架构中引入多线程,实现请求的并发处理,从而提升服务器的吞吐量和响应速度。
- 并发安全设计:学习了如何设计并发安全的服务器结构,确保多个请求在同一时刻处理时互不干扰,数据状态一致。
项目源代码地址:
https://github.com/daichangya/MiniTomcat/tree/chapter7/mini-tomcat
说明:本章代码基于 Java 并发包(java.util.concurrent)实现,适用于 Java 5 及以上版本。示例中的线程池配置主要用于学习与演示,在生产环境中建议根据实际负载情况调整线程池参数,并注意资源泄露风险。 版权声明:本文为原创文章,版权归 戴老师的博客 所有,转载请联系博主获得授权。
本文地址:https://1diff.fun/archives/di-qi-zhang--shi-xian-duo-xian-cheng-zhi-chi-minitomcat.html
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。