Http多线程版本
上一篇文章讲了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多线程版本的更多相关文章
- /MD、/MT、/LD( 使用  多线程版本  运行时库的C runtime library)
		
/MD./MT./LD(使用运行时库)(微软官网解释) Visual C++ 编译器选项 /MD./ML./MT./LD 区别 指定与你项目连接的运行期库 /MT多线程应用程序 /Mtd多线程应用程序 ...
 - Python-爬取校花网视频(单线程和多线程版本)
		
一.参考文章 python爬虫爬取校花网视频,单线程爬取 爬虫----爬取校花网视频,包含多线程版本 上述两篇文章都是对校花网视频的爬取,由于时间相隔很久了,校花网上的一些视频已经不存在了,因此上述文 ...
 - Python-爬取妹子图(单线程和多线程版本)
		
一.参考文章 Python爬虫之——爬取妹子图片 上述文章中的代码讲述的非常清楚,我的基本能思路也是这样,本篇文章中的代码仅仅做了一些异常处理和一些日志显示优化工作,写此文章主要是当做笔记,方便以后查 ...
 - [易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器(多线程版本)]
		
[易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器(多线程版本)] 项目实战 实战3:Http服务器 我们今天来进一步开发我们的Http服务器,用多线程实现. 我 ...
 - Linux网络通信(TCP套接字编写,多进程多线程版本)
		
预备知识 源IP地址和目的IP地址 IP地址在上一篇博客中也介绍过,它是用来标识网络中不同主机的地址.两台主机进行通信时,发送方需要知道自己往哪一台主机发送,这就需要知道接受方主机的的IP地址,也就是 ...
 - Java学习笔记(3)----网络套接字服务器多线程版本
		
本例给出一个客户端程序和一个服务器程序.客户端向服务器发送数据.服务器接收数据,并用它来生成一个结果,然后将这个结果返回给客户端.客户端在控制台上显示结果.在本例中,客户端发送的数据是圆的半径,服务器 ...
 - c++ Socket客户端和服务端示例版本三(多线程版本)
		
客户端 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/soc ...
 - python多线程和多进程对比
		
1.多线程:开启一个进程test.py ,占用两个cpu 共占用45%左右(top -c ,按1) 多进程:开启两个进程test.py 用两个cpu 90%*2左右 test.py # codi ...
 - python高性能代码之多线程优化
		
以常见的端口扫描器为实例 端口扫描器的原理很简单,操作socket来判断连接状态确定主机端口的开放情况. import socket def scan(port): s = socket.socket ...
 
随机推荐
- mysql 查询select语句汇总
			
数据准备: 创建表: create table students( id int unsigned primary key auto_increment not null, name varchar( ...
 - CSS简介及基本知识
			
(CSS)cascading style sheets:层叠样式表.级联式样式表,简称:样式表. Sheets :就是一个样式文件,它的扩展名为.css Style:外观,个性化 样式表的位置 为了学 ...
 - Hive:添加、删除分区
			
添加分区: ', p_loctype='MHA'); 已经创建好的分区表: INFO : Loading partition {p_hour, p_city, p_loctype=MHA} INFO ...
 - ArUco----一个微型现实增强库的介绍及视觉应用(一)
			
ArUco----一个微型现实增强库的介绍及视觉应用(一) 一.ArUco简介 ArUco是一个开源的微型的现实增强库,目前好像已经集成在OpenCV3.0以上的版本内了,它除了用于现实增强,还很用于 ...
 - 南阳OJ-2-括号配对问题---栈的应用
			
题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=2 题目大意: 有一行括号序列,请你检查这行括号是否配对. 思路: 直接用栈来模拟 ...
 - Oracle表空间的管理方式
			
解释说明:表空间是一个逻辑概念:=> oracle 逻辑概念段区块管理方式: number one => tablespace number two=> segments Oracl ...
 - 定点分析: MySQL InnoDB是如何保证系统异常断电情况下的数据可靠性?
			
MySQL支持事务,所以保证数据可靠的前提是对数据的修改事务已经成功提交 这个问题可以解释为'MySQL InnoDB是如何保证事务C(一致性)D(持久性)性的?' 可能出现的两种情况: (一致性)数 ...
 - SpringIOC学习二
			
Spring的IOC容器通过依赖注入DI(dependency injection)来实现程序之间的依赖关系,达到解耦的方式依赖的方式:a.基于xml文件配置的注入 * 构造函数注入 * ...
 - spring data学习
			
在Spring Data模块中定义依赖: <dependencies> <dependency> <groupId>org.springframework.data ...
 - poj 1704 Georgia and Bob(阶梯博弈)
			
Georgia and Bob Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9363 Accepted: 3055 D ...