手写一个民用Tomcat (03)

2024-04-10 10:52
文章标签 tomcat 03 手写 民用

本文主要是介绍手写一个民用Tomcat (03),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们完成了这个 小型Tomcat 基本功能,但是他处理请求还是 一个一个的执行,并不能做到并行处理。 我们仿照Tomcat的思路来进行 一比一精准优化。

 首先看一下我们的JxdHttpConnector 有什么改进,他可以理解成一个快递站领导,统一指挥JxdHttpProcessor 进行 工作。

JxdHttpConnector引入一个队列池,每接到一个请求,就冲队列池中取出来,执行这个请求,执行完之后再放回队列池中,继续等待下一个处理。

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayDeque;
import java.util.Deque;public class JxdHttpConnector implements Runnable {int minProcessors = 3;int maxProcessors = 10;int curProcessors = 0;//存放多个processor的池子Deque<JxdHttpProcessor> processorDeque = new ArrayDeque<>();@Overridepublic void run() {ServerSocket serverSocket = null;int port = 8080;try {serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));} catch (IOException e) {e.printStackTrace();System.exit(1);}//初始化池子 最开始三个initProcessorDeque();while (true) {Socket socket = null;try {//这是单线程 一个请求一个请求获取socketsocket = serverSocket.accept();//得到一个新的processor,这个processor从池中获取(池中有可能新建)JxdHttpProcessor processor = createProcessor();if (processor == null) {socket.close();continue;}processor.assign(socket);} catch (Exception e) {e.printStackTrace();}}}public void start() {Thread thread = new Thread(this);thread.start();}//从池子中获取一个processor,如果池子为空且小于最大限制,则新建一个private JxdHttpProcessor createProcessor() {synchronized (processorDeque) {if (processorDeque.size() > 0) {return processorDeque.pop();}if (curProcessors < maxProcessors) {return newProcessor();} else {return null;}}}private void initProcessorDeque(){for (int i = 0; i < minProcessors; i++) {JxdHttpProcessor processor = new JxdHttpProcessor(this);processor.start();processorDeque.push(processor);}curProcessors = minProcessors;}private JxdHttpProcessor newProcessor() {JxdHttpProcessor jxdHttpProcessor = new JxdHttpProcessor(this);jxdHttpProcessor.start();processorDeque.push(jxdHttpProcessor);curProcessors++;return processorDeque.pop();}public void recycle(JxdHttpProcessor processor) {processorDeque.push(processor);}
}
processorDeque这就是队列池,刚开始的时候 会创建三个,随着业务访问了增加 最多增加10个 ,

你们发现了吗  JxdHttpProcessor 为啥要.start()多线程进行处理,因为 你 虽然引入队列池但是还是不能 解决并行处理问题,所以要让每一个真正的执行者(员工)。进行并行处理。

JxdHttpProcessor 代码:

public class JxdHttpProcessor implements Runnable {boolean available = false;Socket socket;JxdHttpConnector connector;public JxdHttpProcessor(JxdHttpConnector connector) {this.connector = connector;}private void process(Socket socket) { //服务器循环等待请求并处理try {Thread.sleep(3000);} catch (InterruptedException e1) {e1.printStackTrace();}InputStream input = null;OutputStream output = null;try {input = socket.getInputStream();output = socket.getOutputStream();// create Request object and parseJxdRequest request = new JxdRequest(input);request.parse();// create Response objectJxdResponse response = new JxdResponse(output);if (request.getUri().startsWith("/servlet/")) {//加载动态资源JxdServletProcessor jxdServletProcessor = new JxdServletProcessor();jxdServletProcessor.process(request, response);} else {//加载静态资源StaticResourceProcessor staticResourceProcessor = new StaticResourceProcessor();staticResourceProcessor.process(request, response);}//因为是多线程所以只能交给httpProcessor 来关闭socket.close();} catch (Exception ea) {ea.printStackTrace();}}@Overridepublic void run() {while (true) {// 等待socket分配过来Socket socket = await();if (socket == null) continue;// 处理请求process(socket);// 回收processor,员工归队      connector.recycle(this);}}public void start() {Thread thread = new Thread(this);thread.start();}private synchronized Socket await() {// 等待connector提供一个新的socketwhile (!available) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}// 获得这个新的SocketSocket socket = this.socket;//设置标志为falseavailable = false;//通知另外的线程notifyAll();return (socket);}public synchronized void assign(Socket socket) {// 等待connector提供一个新的socketwhile (available) {try {wait();} catch (InterruptedException e) {}}// 获取到这个新的Socketthis.socket = socket;// 把标志设置回去available = true;//通知另外的线程notifyAll();}
}
JxdHttpProcessor 真正的执行者 实现了 Runnable 接口 同时引入了 await()和assign()方法和available 标识。先说await()方法 ,available 默认为false 也就是线程启动的时候进入 等待状态,一直等,等谁呢 他在等待一个指令,就类似于 员工快递站工作,等来了快递 才工作 没有快递 就休息。

在说一下 assign()方法,他的入参是Socket ,表示 快递来了 ,因为available 默认为false所以他会继续走 ,把标志available 默认为true 然后 通知await()中等待的 员工要开始工作了 。

这就是 形成了一套 运行 机制,我通知你干活,你干完活之后 告诉我 ,我们在02那篇文章的时候是这样的,JxdHttpConnector 领导一直紧跟着JxdHttpProcessor 员工,直到员工干完活,一个领导盯着一个员工很累的,现在是 这个领导 统一指挥一个 团队,员工自己干完活之后反馈给领导。

socket.close(); 还记得这个吗。之前是 有JxdHttpConnector 来关闭的,现在由 员工JxdHttpProcessor来关闭了,为啥 因为领导 一致盯着 员工直到 结束,但是现在 盯不住了 ,只能员工自己 才知道什么时候结束 。

备注:其他类不展示 基本每改动。

看一下运行结果吧。 

public class JxdHttpServer {public static final String WEB_ROOT = System.getProperty("user.dir");public static final String FILE_ROOT = "D:\\";public static void main(String[] args) {JxdHttpConnector connector = new JxdHttpConnector();connector.start();}
}

这篇关于手写一个民用Tomcat (03)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/890859

相关文章

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

详解Tomcat 7的七大新特性和新增功能(1)

http://developer.51cto.com/art/201009/228537.htm http://tomcat.apache.org/tomcat-7.0-doc/index.html  Apache发布首个Tomcat 7版本已经发布了有一段时间了,Tomcat 7引入了许多新功能,并对现有功能进行了增强。很多文章列出了Tomcat 7的新功能,但大多数并没有详细解释它们

Tomcat性能参数设置

转自:http://blog.csdn.net/chinadeng/article/details/6591542 Tomcat性能参数设置 2010 - 12 - 27 Tomcat性能参数设置 博客分类: Java Linux Tomcat 网络应用 多线程 Socket 默认参数不适合生产环境使用,因此需要修改一些参数   1、修改启动时内存参数、并指定J

TL-Tomcat中长连接的底层源码原理实现

长连接:浏览器告诉tomcat不要将请求关掉。  如果不是长连接,tomcat响应后会告诉浏览器把这个连接关掉。    tomcat中有一个缓冲区  如果发送大批量数据后 又不处理  那么会堆积缓冲区 后面的请求会越来越慢。

Tomcat下载压缩包解压后应有如下文件结构

1、bin:存放启动和关闭Tomcat的命令的路径。 2、conf:存放Tomcat的配置,所有的Tomcat的配置都在该路径下设置。 3、lib:存放Tomcat服务器的核心类库(JAR文件),如果需要扩展Tomcat功能,也可将第三方类库复制到该路径下。 4、logs:这是一个空路径,该路径用于保存Tomcat每次运行后产生的日志。 5、temp:保存Web应用运行过程中生成的临时文件

Vue day-03

目录 Vue常用特性 一.响应更新 1. 1 v-for更新监测 1.2 v-for就地更新 1.3 什么是虚拟DOM 1.4 diff算法更新虚拟DOM 总结:key值的作用和注意点: 二.过滤器 2.1 vue过滤器-定义使用 2.2 vue过滤器-传参和多过滤器 三. 计算属性(computed) 3.1 计算属性-定义使用 3.2 计算属性-缓存 3.3 计算属

docker学习系列(四)制作基础的base项目镜像--jdk+tomcat

前面已经完成了docker的安装以及使用,现在我们要将自己的javaweb项目与docker结合 1.1准备jdk+tomcat软件 ​​我下载了apache-tomcat-7.0.68.tar.gz和jdk-7u79-linux-x64.tar.gz,存储于Linux机器的本地目录/usr/ect/wt/下(利用xshell上传)。利用linux命令 tar -zxvf apache-tom

stl的sort和手写快排的运行效率哪个比较高?

STL的sort必然要比你自己写的快排要快,因为你自己手写一个这么复杂的sort,那就太闲了。STL的sort是尽量让复杂度维持在O(N log N)的,因此就有了各种的Hybrid sort algorithm。 题主你提到的先quicksort到一定深度之后就转为heapsort,这种是introsort。 每种STL实现使用的算法各有不同,GNU Standard C++ Lib

Tomcat服务详解

一、部署Tomcat服务器 JDK安装官方网址:https://www.oracle.com/cn/java Tomcat安装官方网址:Apache Tomcat® - Welcome! 安装JDK 1.获取安装包wget https://download.oracle.com/otn/java/jdk/8u411-b09/43d62d619be4e416215729597d70b8ac