1. servlet默认是单例模式的,所以是单例多线程的。如果实现了singleservlet是可以多个servlet实例,下面是一个servlet的请求生命周期
    1. 1  

      客户端请求该 Servlet;
      加载 Servlet 类到内存;
      实例化并调用init()方法初始化该 Servlet;
      service()(根据请求方法不同调用doGet() 或者 doPost(),此外还有doHead()、doPut()、doTrace()、doDelete()、doOptions()、destroy())。
      加载和实例化 Servlet。这项操作一般是动态执行的。然而,Server 通常会提供一个管理的选项,用于在 Server 启动时强制装载和初始化特定的 Servlet。
      Server 创建一个 Servlet的实例

      .然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法

    2. servlet可以是异步处理的,work线程立即返回,调用request.startAsync()获取到该请求对应的AsyncContext,然后调用AsyncContext的start()方法进行异步处理。但是另外一个线程池中又新增了一个线程,其中io操作还是会阻塞;
  2. servlet3.0和3.1

https://www.cnblogs.com/davenkin/p/async-servlet.html
在Servlet 3.0之前,Servlet采用Thread-Per-Request的方式处理请求,即每一次Http请求都由某一个线程从头到尾负责处理。如果一个请求需要进行IO操作,比如访问数据库、调用第三方服务接口等,那么其所对应的线程将同步地等待IO操作完成, 而IO操作是非常慢的,所以此时的线程并不能及时地释放回线程池以供后续使用,在并发量越来越大的情况下,这将带来严重的性能问题。即便是像Spring、Struts这样的高层框架也脱离不了这样的桎梏,因为他们都是建立在Servlet之上的。为了解决这样的问题,Servlet 3.0引入了异步处理,然后在Servlet 3.1中又引入了非阻塞IO来进一步增强异步处理的性能。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AsyncContext asyncContext = request.startAsync(); asyncContext.start(() -> {
new LongRunningProcess().run();
try {
asyncContext.getResponse().getWriter().write("Hello World!");
} catch (IOException e) {
e.printStackTrace();
}
asyncContext.complete();
}); }

此时,我们先通过request.startAsync()获取到该请求对应的AsyncContext,然后调用AsyncContext的start()方法进行异步处理,处理完毕后需要调用complete()方法告知Servlet容器。start()方法会向Servlet容器另外申请一个新的线程(可以是从Servlet容器中已有的主线程池获取,也可以另外维护一个线程池,不同容器实现可能不一样),然后在这个新的线程中继续处理请求,而原先的线程将被回收到主线程池中。事实上,这种方式对性能的改进不大,因为如果新的线程和初始线程共享同一个线程池的话,相当于闲置下了一个线程,但同时又占用了另一个线程。

Servlet 3.0对请求的处理虽然是异步的,但是对InputStream和OutputStream的IO操作却依然是阻塞的,对于数据量大的请求体或者返回体,阻塞IO也将导致不必要的等待。因此在Servlet 3.1中引入了非阻塞IO(参考下图红框内容),通过在HttpServletRequest和HttpServletResponse中分别添加ReadListener和WriterListener方式,只有在IO数据满足一定条件时(比如数据准备好时),才进行后续的操作。

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AsyncContext asyncContext = request.startAsync();
ServletInputStream inputStream = request.getInputStream();
inputStream.setReadListener(new ReadListener() {
@Override
public void onDataAvailable() throws IOException {
}
@Override
public void onAllDataRead() throws IOException {
executor.execute(() -> {
new LongRunningProcess().run();
try {
asyncContext.getResponse().getWriter().write("Hello World!");
} catch (IOException e) {
e.printStackTrace();
}
asyncContext.complete();
});
}
@Override
public void onError(Throwable t) {
asyncContext.complete();
}
});
}
}

servlet 最大线程数探索笔记的更多相关文章

  1. (笔记)Linux 如何查看线程数最佳解决方案

    背景:很多学linux的人都会使用ps查看进程状态,却一直不清楚如何查看线程的状态. 方法:可使用ps -a 或 ps -T命令查看 一.使用ps -a命令查看 比如拿我的测试进程./lc300-le ...

  2. Dubbo入门到精通学习笔记(十一):Dubbo服务启动依赖检查、Dubbo负载均衡策略、Dubbo线程模型(结合Linux线程数限制配置的实战分享)

    文章目录 Dubbo服务启动依赖检查 Dubbo负载均衡策略 Dubbo线程模型(结合Linux线程数限制配置的实战分享) 实战经验分享( ** 属用性能调优**): Dubbo服务启动依赖检查 Du ...

  3. android中的线程池学习笔记

    阅读书籍: Android开发艺术探索 Android开发进阶从小工到专家 对线程池原理的简单理解: 创建多个线程并且进行管理,提交的任务会被线程池指派给其中的线程进行执行,通过线程池的统一调度和管理 ...

  4. 一个使用高并发高线程数 Server 使用异步数据库客户端造成的超时问题

    现象 今天在做一个项目时, 将 tomcat 的 maxThreads 加大, 加到了 1024, tomcat 提供的服务主要是做一些运算, 然后插入 redis, 查询 redis, 最后将任务返 ...

  5. 详解tomcat连接数和线程数

    前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server.xm ...

  6. Java多线程之如何确定线程数

    关于多线程的线程数的确定,最近研读过几篇paper,在此做一下笔记,方便使用时翻看. 1.<Java 虚拟机并发编程>中介绍 就是说:线程数 =  CPU的核心数 * (1 - 阻塞系数) ...

  7. Python数模笔记-StatsModels 统计回归(4)可视化

    1.如何认识可视化? 图形总是比数据更加醒目.直观.解决统计回归问题,无论在分析问题的过程中,还是在结果的呈现和发表时,都需要可视化工具的帮助和支持. 需要指出的是,虽然不同绘图工具包的功能.效果会有 ...

  8. Python数模笔记-StatsModels 统计回归(1)简介

    1.关于 StatsModels statsmodels(http://www.statsmodels.org)是一个Python库,用于拟合多种统计模型,执行统计测试以及数据探索和可视化. 2.文档 ...

  9. Linux上如何查看物理CPU个数,核数,线程数

    首先,看看什么是超线程概念 超线程技术就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的 ...

随机推荐

  1. Xcode 和 VisualC++输出流的差别的理解

    将这样一段程序分别运行与Visual Studio 和 Xcode上边的结果: #include <iostream> using namespace std; int main() { ...

  2. CIFAR-10数据集读取

    参考:https://jingyan.baidu.com/article/656db9183296c7e381249cf4.html 1.使用读取方式pickle def unpickle(file) ...

  3. linux的基本操作1

    文件系统 ext4 d: 进入d盘dir /w 以友好的方式列出目录cd     目录名 进入目录cd\      退出目录cd ..    退出到上级目录ipconfig /all 显示本机网络信息 ...

  4. python------面向对象进阶 异常处理

    一. 异常处理 try: pass except KeyError as e : #注3.x用as ,except KeyError, e ,2.x 用逗号. print("No this ...

  5. MySQL 中,字符串 0 和数字 0 的区别

    我的理解: 用户输入值后,MySQL 根据该字段的数据类型,来转换值.

  6. WPF项目中解决ConfigurationManager不能用(转)

    https://blog.csdn.net/MOESECSDN/article/details/78107888 在WPF项目中遇到这样的问题,做一下笔记.希望对自己和读者都有帮助. 在aap.con ...

  7. 互联网同步yum服务器阿里云 reposync createrepo

    参考文章: https://www.cnblogs.com/lldsn/p/10479493.html 系统版本centos 7.5 最小化安装 修改主机名 hostnamectl set-hostn ...

  8. Python变量以及类型

    变量的定义 在程序中,有时我们需要对2个数据进行求和,那么该怎样做呢? 大家类比一下现实生活中,比如去超市买东西,往往咱们需要一个菜篮子,用来进行存储物品,等到所有的物品都购买完成后,在收银台进行结账 ...

  9. JavaScript常见的代码精简

    1.&& callback && callback() 等价于: if(callback){ callback(); } 表达的意思: 先判断 callback 是不是 ...

  10. Cookie深度解析

    最近在公司做了Web端单点登录(SSO)功能,基于Cookie实现,做完之后感觉有必要总结一下,本文着重讲解Cookie,下文会说明单点登录的实现方案. Cookie简介 众所周知,Web协议(也就是 ...