上一篇文章讲了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. python 资产管理

    python 资产管理 一.Agent 方式 1.这个方法的优点:使用简单,速度快,适合服务器较多场景使用,缺点:服务器比较占资源,性能会变低. 2.使用Agent的前提条件是客户端(服务器)特别多的 ...

  2. Http post请求数据分析 --作者, 你的这个需求我可以做, 我在平台上无法给你发消息和接收你的任务, 所以,如果你看到这个信息, 可以联系我.

    Http post请求数据分析 作者, 你的这个需求我可以做, 我在平台上无法给你发消息和接收你的任务, 所以,如果你看到这个信息, 可以联系我. 软件需求就是不停post一个网址,然后根据返回的信息 ...

  3. java字符串类型常量拼接与变量拼接的区别

    前言 首先看下下面代码结果是什么? package cn.demo_01; public class StringDemo02 { public static void main(String[] a ...

  4. 05、NetCore2.0依赖注入(DI)之Web应用启动流程管理

    05.NetCore2.0依赖注入(DI)之Web应用启动流程管理 在一个Asp.net core 2.0 Web应用程序中,启动过程都做了些什么?NetCore2.0的依赖注入(DI)框架是如何管理 ...

  5. linux系统环境与文件权限

    默认有6个命令交互通道和一个图形界面交互通道,默认进入到的是图形界面通道 命令交互模式切换:ctrl+alt+f1---f6 图形交互界面 ctrl+alt+f7 1.图形界面交互模式 - termi ...

  6. 关于terraform的状态管理

    我们想在aws创建3台主机,使用ansible和terraform都是可以实现的. 用ansible可能是这样子的: - ec2: count: 10 image: ami-40d281120 ins ...

  7. SVN上传项目步骤

    1.svn上传项目  首先选中父工程 ,右键选中Team的share project 2.share完再选中SVN 3.选中项目  一个一个share project 4.

  8. spring boot / cloud (四) 自定义线程池以及异步处理@Async

    spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...

  9. redis安装异常的解决的办法

    在开始redis安装的时候,先废话一下 官网: 英文 :https://redis.io/ 中文 :http://www.redis.cn/ 首先我们需要一个linux服务器,当然windows也是可 ...

  10. Linux服务器断电导致挂载及xfs文件损坏的修复方法

    系统文件损坏后进入紧急修复模式,无法进行维护工作 welcome to emergency mode!after logging in ,type "journalctl -xb" ...