手写一个民用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<>();

    @Override
    public 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 {
                //这是单线程 一个请求一个请求获取socket
                socket = 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 parse
            JxdRequest request = new JxdRequest(input);
            request.parse();
            // create Response object
            JxdResponse 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();
        }
    }


    @Override
    public 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提供一个新的socket
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 获得这个新的Socket
        Socket socket = this.socket;
        //设置标志为false
        available = false;
        //通知另外的线程
        notifyAll();
        return (socket);
    }

    public synchronized void assign(Socket socket) {
        // 等待connector提供一个新的socket
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        // 获取到这个新的Socket
        this.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来关闭了,为啥 因为领导 一致盯着 员工直到 结束,但是现在 盯不住了 ,只能员工自己 才知道什么时候结束 。

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

看一下运行结果吧。 文章来源地址https://www.toymoban.com/news/detail-853664.html

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)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手写模拟SpringBoot核心流程(二):实现Tomcat和Jetty的切换

    上一篇文章我们聊到,SpringBoot中内置了web服务器,包括Tomcat、Jetty,并且实现了SpringBoot启动Tomcat的流程。 那么SpringBoot怎样自动切换成Jetty服务器呢? 接下来我们继续学习如何实现Tomcat和Jetty的自动切换。 将BerSpringApplication类中startTomcat写到TomcatWebServer实现类中。 JettyWebServe

    2024年02月12日
    浏览(32)
  • web server apache tomcat11-03-deploy 如何部署

    整理这个官方翻译的系列,原因是网上大部分的 tomcat 版本比较旧,此版本为 v11 最新的版本。 从零手写实现 tomcat minicat 别称【嗅虎】心有猛虎,轻嗅蔷薇。 web server apache tomcat11-01-官方文档入门介绍 web server apache tomcat11-02-setup 启动 web server apache tomcat11-03-deploy 如何部署 web

    2024年04月17日
    浏览(31)
  • 一个 tomcat 下如何部署多个项目?附详细步骤

    一个tomcat下如何部署多个项目?Linux跟windows系统下的步骤都差不多,以下linux系统下部署为例。windows系统下部署同理。 清楚tomcat目录结构的应该都知道,项目包是放在webapps目录下的,那能否在同一个tomcat的webapps目录下运行多个不同项目呢? 答案是可以的。 1、将多个项目包

    2024年02月07日
    浏览(29)
  • JavaEE & Tomcat & Servelet第一个helloworld程序

    Tomcat Servelet第一个程序helloworld! HTTP本质上就是一个TCP服务器(HTTP基于TCP) 这个服务器按照HTTP协议的约定,解析请求,构造响应 你自己写一个HTTP服务器,也完全没问题! 不过我们Java圈子和生态中,有一个现成的,最流行的,apache社区开源的http服务器 = = =》 Tomcat 直接去官

    2024年02月07日
    浏览(32)
  • 【Tomcat】如何在idea上部署一个maven项目?

    目录 1.创建项目 2.引入依赖 3.创建目录 4.编写代码 5.打包程序 6.部署项目 7.验证程序 什么是Tomcat和Servlet? 以idea2019为例: 1.创建项目 1.1 首先创建maven项目 1.2 项目名称    2.引入依赖 2.1 网址输入 mvnrepository.com 进入maven中央仓库-地址。点击搜索 servlet,找到Java Servlet API。  2

    2024年02月08日
    浏览(46)
  • 【JavaEE】Tomcat-Servelet第一个helloworld程序

    Tomcat Servelet第一个程序helloworld! HTTP本质上就是一个TCP服务器(HTTP基于TCP) 这个服务器按照HTTP协议的约定,解析请求,构造响应 你自己写一个HTTP服务器,也完全没问题! 不过我们Java圈子和生态中,有一个现成的,最流行的,apache社区开源的http服务器 = = =》 Tomcat 直接去官

    2024年02月09日
    浏览(26)
  • 2022版本IDEA+Maven+Tomcat的第一个程序(傻瓜教学)

    ​ 作为学习Javaweb的一个重要环节,如何实现在IDEA中利用Maven工具创建一个Javaweb程序模版并连接Tomcat发布是非常重要的。我比较愚钝(小白),而且自身电脑先前运行过spring或maven的程序,系统内有一些IDEA安装的文件,因此花了点时间才配出来。这里写一篇傻瓜博客讲一下如

    2024年02月07日
    浏览(28)
  • TOMCAT部署及优化(Tomcat配置文件参数优化,Java虚拟机(JVM)调优)

    TOMCAT tomcat :是一个开放源代码的web应用服务器,基于java代码开发的。也可以理解为tomacat就是处理动态请求和基于java代码的页面开发。可以在html当中写入java代码,tomcat可以解析html页面当中的java,执行动态请求,动态页面。 tomcat是机制存在一些问题,如果不对tomcat进行优化

    2024年02月13日
    浏览(21)
  • Tomcat:Java Web

    简介 Apache Tomcat 是 Java Web 应用程序开发中最为常用的服务器之一。作为一个开源、轻量级的 Servlet 容器和 JSP 容器,Tomcat 提供了一个稳定可靠的运行环境,使得开发者可以快速开发、部署和管理 Java Web 应用程序。本文将深入介绍 Tomcat 的特点、优势、安装、配置和基本用法,

    2024年03月23日
    浏览(33)
  • JAVA配置tomcat

    IDEA新建module的时候没有javaee的选项,这时候可以先选择普通的java项目进行创建。 图片中的a就是新建的java module。 右键a文件夹,选择Add Framework Support。 然后选中Web Application,点击右下角的ok即可。 a文件夹下出现带小蓝的web就说明成功了。 关联相关包 将jar包拷到libs文件夹下

    2023年04月08日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包