手写简易版Tomcat第二天

本文介绍了如何使用Java的ExecutorService和固定线程池在TomCat风格下实现多线程的HTTP通信,通过创建TomCatThreadPool类,处理来自客户端的Socket请求,避免了单线程的低效问题。

前言

        上篇文章中,实现了浏览器与服务器之间的通信,但是是单线程下的通信,效率低下。这篇文章,通过线程池来实现多线程通信。但TomCat除了具有线程池外,还具有一个任务队列来存储没来得及处理的请求,我暂时不会像TomCat一样让线程池从任务队列中获取请求,而是一个固定的线程池,有请求就去处理。

代码实现

我们创建个线程池类

public class TomCatThreadPool {
    ExecutorService executor = null;
    //线程数量
    int coreNum;

    public TomCatThreadPool(int coreNum) {
        System.out.println("初始化TomCat的线程池");
        this.coreNum = coreNum;
        executor = Executors.newFixedThreadPool(coreNum);
    }

    public void execute(Socket socket) {
        executor.execute(()->{
            System.out.println(Thread.currentThread().getName()+"开始处理请求");
            InputStream inputStream = null;
            try {
                inputStream = socket.getInputStream();
                //设置编码为UTF-8,并以字符的形式读取
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String msg = null;
                //循环读取
                while ((msg = bufferedReader.readLine()) != null) {
                    if (msg.length() == 0) {
                        break;
                    }
                    //讲读取的信息打印在控制台上
                    System.out.println(msg);
                }

                //读取完毕后,进行一个简单响应
                OutputStream outputStream = socket.getOutputStream();
                String responseHead = "HTTP/1.1 200\r\n" +
                        "Content-Type: text/html;charset=utf-8\r\n\r\n";
                String responseBody = "这是一个简单的展示页面";
                String response = responseHead + responseBody;
                //将数据展示给浏览器
                outputStream.write(response.getBytes());
                outputStream.close();
                inputStream.close();
                socket.close();
                System.out.println("断开连接...");
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

}

该线程池类,里面存在一个固定线程池,线程池中的线程数量由主程序决定,线程池中的线程用来处理请求而不是主线程处理,将第一节中的大部分代码粘到线程池中执行。

那么主程序中就变成如下代码

    public static void main(String[] args) {
        TomCatThreadPool threadPool = new TomCatThreadPool(2);
        try {
            //监听8080端口
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("我的服务器启动成功...");
            //socket没接收到关闭事件之前不退出循环
            while (!serverSocket.isClosed()) {
                System.out.println("等待连接...");
                //等待连接,该事件会阻塞线程
                Socket socket = serverSocket.accept();
                System.out.println("连接成功...");
                threadPool.execute(socket);
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器启动失败");
        }
    }

测试

访问8080端口,可以看到线程池中的线程去处理请求。而不是主线程

至此实现了多线程通信。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zmbwcx2003

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值