上一篇文章讲了HTTP是如何通过TCP协议传输到服务器上,以及服务器接收到的报文信息
请参考[HTTP与TCP的关系]

这篇文章主要讲述的多线程处理Http请求,关于多线程的好处我就不再叙述了。由于我们的
请求处理可能非常的耗时,导致服务器无法在规定的时间内出力请求,这样服务器的吞吐量比较低,
为了达到高吞吐量,往往在请求处理时使用多线程技术,不会影响接受请求线程,这样一来即使处理
请求的线程堵塞了也不会影响处理请求的线程,这个也是现在比较流行的Reactor模型。

首先来看看处理请求的线程代码:

/**
* 处理HTTP请求的一个类
* @author xin.qiliuhai 1045931706@qq.com
* @date 2018/4/29 19:15
*/
public class HttpHandler implements Runnable {
private Socket socket;
public HttpHandler(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
BufferedWriter bw=null;
try{
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String s;
int contentLength = 0;
//4.输出请求体中的内容,并且将Content-Length的值赋值给contentLength,确定post请求体的大小
while ((s = br.readLine()) != null && !s.isEmpty()) {
System.out.println(s);
if (s.indexOf("Content-Length") != -1) {
contentLength = Integer.parseInt(s.substring(s.indexOf("Content-Length") + 16));
}
}
//5.如果有请求体,通过read方法读取请求体中的内容
if (contentLength != 0) {
char[] buf = null;
if (contentLength != 0) {
buf = new char[contentLength];
br.read(buf, 0, contentLength);
System.out.println("The data user posted: " + new String(buf));
}
}
//6 设置响应体内容
bw.write("HTTP/1.1 200 OK\n");
bw.write("Content-Type: text/html; charset=UTF-8\n\n");
bw.write("<html>\n" +
"<head>\n" +
" <title>first page</title>\n" +
"</head>\n" +
"<body>\n" +
" <h1>Hello World!" + "</h1>\n" +
"</body>\n" +
"</html>\n");
//7.冲刷到浏览器
bw.flush();
bw.close();
br.close(); //阻塞十秒钟 相当于在执行请求时堵塞了
Thread.sleep(10000);
}catch (Exception ex){
ex.printStackTrace();
}
}
}

单线程调用

/**
* HTTP报文
* @author xin.qiliuhai 1045931706@qq.com
* @date 2018/4/29 9:09
*/
public class HttpDemo {
public static void main(String[] args) throws Exception {
ServerSocket ss = null;
Socket socket = null;
try {
//1.创建socket连接
ss = new ServerSocket(8080);
//循环等待
while (true) {
//2.堵塞,直到有新的连接进来
socket = ss.accept();
//3处理相应的请求,这个方法会堵塞
new HttpHandler(socket).run();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
ss.close();
}
}
}

大家可以尝试一下,第一次请求速度比较快,后面的请求必须至少等10秒才能进行,所以一旦请求处理
线程堵塞了会严重影响后面的请求,这个也是netty中一直强调的不要再主线程中调用耗时比较长的方法。

多线程版本1

/**
* @author xin.qiliuhai 1045931706@qq.com
* @date 2018/4/29 20:03
*/
public class HttpSimpleThread {
public static void main(String[] args)throws Exception{
//创建一个与CPU一样的的
ServerSocket ss = null;
Socket socket = null;
try {
while(true){
//1.创建socket连接
ss = new ServerSocket(8081);
//循环等待
while (true) {
socket=ss.accept();
//一个请求对应一个线程,请求直接交给线程进行处理
new Thread(new HttpHandler(socket)).start();
ss.close();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
ss.close();
}
}
}

每当来一个请求新建一个线程请求,但是我们知道一个电脑同时能处理的线程是十分有限的,创建与销毁线程

是需要占用一部分时间的,而且涉及到核心态与用户态之间的转换,我们可以理解一个请求时间=tcp时间+线程
创建时间+处理请求时间+销毁线程时间,那么有没有一种可能将线程创建与销毁时间做到忽略不计呢?答案是有的,
我们可以将处理请求的线程放到线程池中运行,这样减少很大一部分时间上的开销。

多线程版本2

/**
* @author xin.qiliuhai 1045931706@qq.com
* @date 2018/4/29 19:13
*/
public class HttpThreads {
public static void main(String[] args)throws Exception{
//创建一个与计算机线程数相同的不可变线程
Executor executor= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
ServerSocket ss = null;
Socket socket = null;
BufferedReader br = null;
BufferedWriter bw = null;
try {
//1.创建socket连接
ss = new ServerSocket(8081);
//循环等待
while (true) {
socket=ss.accept();
//2.将线程放入到线程池中运行
executor.execute(new HttpHandler(socket));
//Thread.sleep(10000);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
ss.close();
}
}
}

当然在这里面的还有很多工作需要进行,比如当线程池满了,对新来的线程进行如何操作,对HTTP请求的解码与编码怎么处理
还有如果直到某个请求一定会占用比较长的时间怎么处理。这些将会在之后的文章进行讨论。

Http多线程版本的更多相关文章

  1. /MD、/MT、/LD( 使用 多线程版本 运行时库的C runtime library)

    /MD./MT./LD(使用运行时库)(微软官网解释) Visual C++ 编译器选项 /MD./ML./MT./LD 区别 指定与你项目连接的运行期库 /MT多线程应用程序 /Mtd多线程应用程序 ...

  2. Python-爬取校花网视频(单线程和多线程版本)

    一.参考文章 python爬虫爬取校花网视频,单线程爬取 爬虫----爬取校花网视频,包含多线程版本 上述两篇文章都是对校花网视频的爬取,由于时间相隔很久了,校花网上的一些视频已经不存在了,因此上述文 ...

  3. Python-爬取妹子图(单线程和多线程版本)

    一.参考文章 Python爬虫之——爬取妹子图片 上述文章中的代码讲述的非常清楚,我的基本能思路也是这样,本篇文章中的代码仅仅做了一些异常处理和一些日志显示优化工作,写此文章主要是当做笔记,方便以后查 ...

  4. [易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器(多线程版本)]

    [易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器(多线程版本)] 项目实战 实战3:Http服务器 我们今天来进一步开发我们的Http服务器,用多线程实现. 我 ...

  5. Linux网络通信(TCP套接字编写,多进程多线程版本)

    预备知识 源IP地址和目的IP地址 IP地址在上一篇博客中也介绍过,它是用来标识网络中不同主机的地址.两台主机进行通信时,发送方需要知道自己往哪一台主机发送,这就需要知道接受方主机的的IP地址,也就是 ...

  6. Java学习笔记(3)----网络套接字服务器多线程版本

    本例给出一个客户端程序和一个服务器程序.客户端向服务器发送数据.服务器接收数据,并用它来生成一个结果,然后将这个结果返回给客户端.客户端在控制台上显示结果.在本例中,客户端发送的数据是圆的半径,服务器 ...

  7. c++ Socket客户端和服务端示例版本三(多线程版本)

    客户端 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/soc ...

  8. python多线程和多进程对比

    1.多线程:开启一个进程test.py ,占用两个cpu  共占用45%左右(top -c ,按1)  多进程:开启两个进程test.py 用两个cpu  90%*2左右 test.py # codi ...

  9. python高性能代码之多线程优化

    以常见的端口扫描器为实例 端口扫描器的原理很简单,操作socket来判断连接状态确定主机端口的开放情况. import socket def scan(port): s = socket.socket ...

随机推荐

  1. layer ui插件显示tips时,修改字体颜色

    今天做调查问卷,又遇到一个蛋疼小问题,记录下. 调查问卷有很多选项是要求必填的,如果不填的话,需要给出友好的提示.用的如下组件:http://layer.layui.com/ 1.之前一直默认用的: ...

  2. Struts(十八):通过CURD来学习PrepareInterceptor拦截器

    PrepareInterceptor拦截器的用法: 1.若Action实现了Preparable接口,则Action方法需实现prepare()方法: 2.PrepareInterceptor拦截器S ...

  3. 处理异常、常用类、反射、类加载与垃圾回收、java集合框架

    异常处理概述 检查异常:检查异常通常是用户错误或者不能被程序员所预见的问题.(cheched) 运行时异常:运行时异常是一个程序在运行过程中可能发生的.可以被程序员避免的异常类型.(Unchecked ...

  4. jacascript 事件流

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 事件流 当浏览器发展到第四代时(IE4及Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面 ...

  5. 在windows系统之中查看目前已安装的更新

    方法1:使用PowerShell get-hotfix 方法2:使用cmd systeminfo.exe 参考链接

  6. eclipse下maven插件搭建springmvc之helloworld

    这几天学习了怎样使用maven,最终还是要回归web项目嘛,所以主要还是使用eclipse插件. 1 下载eclipse maven插件. 其实新版的eclipse已经集成了maven:lunar.m ...

  7. eclipse导包导不进来

    今天某个类转移了位置,结果导包导不进来: 解决方法:1.查看本项目中pom的依赖关系,查看是否引用了转移后的项目. 2.查看导不进来的报错类,查看类刚开始import的信息,如果有报错,删除后重新导包 ...

  8. 关于 Rijndael 加密

    MSDN https://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rijndaelmanaged(v=vs.110) ...

  9. svg从入门到装逼(一)

    svg文件是基于xml的矢量图,而canvas是基于html和js的位图.关于两者的比较,在粗就不赘述了. 1.  首先来上一个svg的基本结构: <?xml version="1.0 ...

  10. SpringMVC 教程 - Controller

    原文地址:https://www.codemore.top/cates/Backend/post/2018-04-10/spring-mvc-controller 声明Controller Contr ...