点击查看代码
public class DiyTomcat {

    private int port = 8080;

    public static final HashMap<String, DiyServlet> SERVLET_MAPPING = new HashMap<>();

    public static final HashMap<String,String> URL_MAPPING = new HashMap<>();

    private static ThreadPoolExecutor threadPoolExecutor;

    static {
loadServlet();
initExecutors();
} // 线程池化
private static void initExecutors() {
int corePoolSize = 10;
int maximumPoolSize = 50;
long keepAliveTime = 100L;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler
);
} private static void loadServlet() {
try {
//获取web.xml目录地址
String path = DiyTomcat.class.getResource("/").getPath();
SAXReader reader = new SAXReader();
//读取web.xml文件
Document document = reader.read(new File(path + "web.xml"));
//获取根标签(servlet和servlet-mapping),放在一个List中
Element rootElement = document.getRootElement();
List<Element> elements = rootElement.elements();
//循环将映射写进map映射里
for(Element element : elements){
if ("servlet".equalsIgnoreCase(element.getName())){
Element servletName = element.element("servlet-name");
Element servletClass = element.element("servlet-class");
//需要注意的是servletMapping映射的第二个参数,要通过反射的方式进行实例化
SERVLET_MAPPING.put(servletName.getText(),
(DiyServlet) Class.forName(servletClass.getText().trim()).newInstance());
}else if ("servlet-mapping".equalsIgnoreCase(element.getName())){
Element servletName = element.element("servlet-name");
Element urlPattern = element.element("url-pattern");
URL_MAPPING.put(urlPattern.getText(), servletName.getText());
}
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
} public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
Socket socket = serverSocket.accept();
RequestHandler requestHandler = new RequestHandler(socket);
// 一个 socket 一个线程
// new Thread(requestHandler).start();
// 使用线程组干活
threadPoolExecutor.execute(requestHandler);
}
}
}
  1. 通过initExecutors方法创建出一个线程池
    private static void initExecutors() {
// 核心线程数
int corePoolSize = 10;
// 最大线程数
int maximumPoolSize = 50;
// 空闲线程保活时间
long keepAliveTime = 100L;
// 保活单位,当前设置为秒
TimeUnit unit = TimeUnit.SECONDS;
// 线程池队列
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
// 线程创建工厂
ThreadFactory threadFactory = Executors.defaultThreadFactory();
// 池子满后的拒绝请求处理器
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler
);
}
  1. accept到socket后直接包装成RequestHandler交由线程池处理
while (true) {
Socket socket = serverSocket.accept();
RequestHandler requestHandler = new RequestHandler(socket);
// 一个 socket 一个线程
// new Thread(requestHandler).start();
// 使用线程组干活
threadPoolExecutor.execute(requestHandler);
}

代码地址:

https://github.com/ZhongJinHacker/diy-tomcat/tree/pool-tomcat

手写tomcat——有线程池化能力的servlet 服务的更多相关文章

  1. Java多线程之Executor框架和手写简易的线程池

    目录 Java多线程之一线程及其基本使用 Java多线程之二(Synchronized) Java多线程之三volatile与等待通知机制示例 线程池 什么是线程池 线程池一种线程使用模式,线程池会维 ...

  2. 手写tomcat——概述

    1. 使用java 编写一个echo http服务器 使用java 编写一个echo http服务器 https://github.com/ZhongJinHacker/diy-tomcat/tree ...

  3. 每天都在用,但你知道 Tomcat 的线程池有多努力吗?

    这是why的第 45 篇原创文章.说点不一样的线程池执行策略和线程拒绝策略,探讨怎么让线程池先用完最大线程池再把任务放到队列中. 荒腔走板 大家好,我是 why,一个四川程序猿,成都好男人. 先是本号 ...

  4. 手写Tomcat

    学习JavaWeb之后,只知道如何部署项目到Tomcat中,而并不了解其内部如何运行,底层原理为何,因此写下此篇博客初步探究一下.学习之前需要知识铺垫已列出:Tomcat目录结构.HTTP协议.IO. ...

  5. 关于 Tomcat 的线程池的理解

    默认配置下,Tomcat 会为每个连接器创建一个绑定的线程池(最大线程数 200).在大多数情况下你不需要改这个配置(除非增大最大线程数以满足高负载需要).但是 Tomcat 喜欢在每个工作者线程的 ...

  6. 手写Tomcat服务器

    预备知识 编写服务器用到的知识点 1) Socket 编程2) HTML3) HTTP 协议4) 反射5) XML 解析6) 服务器编写 Socket编程 https://www.cnblogs.co ...

  7. tomcat使用线程池配置高并发连接

    1:配置executor属性打开/conf/server.xml文件,在Connector之前配置一个线程池:[html] view plain copy<Executor name=" ...

  8. 自己动手写http服务器——线程池(一)

    创建一个线程池,每有一个连接对象就将它添加到工作队列中,线程池中的线程通过竞争来取得任务并执行它(它是通过信号量实现的). //filename threadpool.h #ifndef THREAD ...

  9. java 从零开始手写 RPC (05) reflect 反射实现通用调用之服务端

    通用调用 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何 ...

随机推荐

  1. sql-扩展sql

    复制表结构 create table 表名 like 被复制的表名; -- 仅复制表表结构 oracle不支持 复制表结构和数据(子查询方式) CREATE TABLE 表名 [AS] SELECT ...

  2. vue2.0 双向绑定原理分析及简单实现

    Vue用了有一段时间了,每当有人问到Vue双向绑定是怎么回事的时候,总是不能给大家解释的很清楚,正好最近有时间把它梳理一下,让自己理解的更清楚,下次有人问我的时候,可以侃侃而谈. 一.首先介绍Obje ...

  3. 基于UniApp社区论坛多端开发实战

    什么是移动端WebApp 移动端WebApp: 泛指手持设备移动端的web 特点: - 类App 应用,运行环境是浏览器 - 可以包一层壳,成为App - 常见的混合应用: ionic, Cordov ...

  4. 练习-用if语句替换三元运算符和选择结构-标准的switch语句

    if语句和三元运算符的互换 在某些简单的应用中,if语句是可以和三元运算符互换使用的 public static void main(String[] args) { int a = 10; int ...

  5. JUC源码学习笔记1——AQS和ReentrantLock

    笔记主要参考<Java并发编程的艺术>并且基于JDK1.8的源码进行的刨析,此篇只分析独占模式,后续在ReentrantReadWriteLock和 CountDownLatch中 会重点 ...

  6. 基于 Rainbond 部署 DolphinScheduler 高可用集群

    本文描述通过 Rainbond 云原生应用管理平台 一键部署高可用的 DolphinScheduler 集群,这种方式适合给不太了解 Kubernetes.容器化等复杂技术的用户使用,降低了在 Kub ...

  7. logrotate command in Linux

    背景 在生产过程中,由于磁盘空间.保留周期等因素,会对系统.应用等日志提出要求,要求系统日志定期进行轮转.压缩和删除,从而减少开销,而系统自带的logrotate  则是一个简单又实用的小工具,下面着 ...

  8. C++ 练气期之函数探幽

    1. 函数基础 一个C++程序中,往往需要包含若干个函数,可以说函数是C++程序的基础组成元件,是程序中的头等公民. 如果要理解程序中使用函数的具体意义,则需要了解语言发展过程中致力要解决的 2 问题 ...

  9. 【转载】一封面向社会,关于对近日来 CCF 不当行为之抗议的公开信

    原文链接:https://101001011.github.io/2022/06/11/zhi-ccf-de-yi-feng-gong-kai-xin/ 原文作者:CCA(CCA's Blog) 前天 ...

  10. vue中vuex实现持久化的几种方法

    前提:大家都知道vuex真的数据共享是不持久的,例如登录后一刷新,state中存的token就会消失,导致你需要再次进行登录操作 在这给大家列出几种解决方案: 第一种(也是一些项目中常使用的):使用缓 ...