网络I/O模型--02阻塞模式(多线程)
当服务器收到客户端 X 的请求后(读取到所有请求数据后),将这个请求送入一个独立线程进行处理,然后主线程继续接收客户端 Y 的请求。
客户端一侧也可以使用一个子线程和服务器端进行通信。这样客户端主线程的其他工作就不受影响了,当服务器端有响应信息时再由这个子线程通过监听模式/观察模式或者类似的其他设计模式通知主线程。
服务端
package testBlockSocket; import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; // 通过多线程的方式处理socket的连接
public class SocketServer2MiltiThread {
private final static Logger LOGGER = LoggerFactory.getLogger(SocketServer2MiltiThread.class); public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
try {
while (true) {
Socket socket = serverSocket.accept();
// 业务处理过程可以交给一个线程,不过线程的创建很耗资源
// 最终改变不了, accept () 只能在被阻塞的情况一个一个接收 Socket
SocketServerThread socketServerThread = new SocketServerThread(socket);
Thread thread = new Thread(socketServerThread);
thread.start();
}
} catch (Exception e) {
SocketServer2MiltiThread.LOGGER.error(e.getMessage(), e);
} finally {
if (serverSocket != null) {
serverSocket.close();
// 当然 , 接收到客户端的 Socket 后 , 业务的处理过程可以交给一个线程来做
}
}
} } class SocketServerThread implements Runnable {
private final static Logger LOGGER = LoggerFactory.getLogger(SocketServerThread.class); private Socket socket; public SocketServerThread(Socket socket) {
this.socket = socket;
} @Override
public void run() {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
// 下面我们收取信息
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
Integer sourcePort = socket.getPort();
int maxLen = 1024;
byte[] contextBytes = new byte[maxLen];
// 同样无法改变 read 方法被阻塞,直到操作系统有数据准备好的现象
int realLen = inputStream.read(contextBytes, 0, maxLen);
String message = new String(contextBytes, 0, realLen);
LOGGER.info("服务器收到来自于端曰 :" + sourcePort + " 的信息:" + message);
// 下面开始发送响应信息
outputStream.write("因发响应信息 !".getBytes());
} catch (Exception e) {
SocketServerThread.LOGGER.error(e.getMessage(), e);
} finally {
// 试图关闭连接
try {
inputStream.close();
outputStream.close();
socket.close();
} catch (Exception e) {
SocketServerThread.LOGGER.error(e.getMessage(), e);
}
}
} }
1)虽然在服务器端,接收到数据后的处理交给了 一个独立线程进行,但是操作系 统通知accept()的方式还是单个线程运行的 。 也就是说,实际上是服务器接收到数据报文后的“业务处理过程”可以应用多线程技术,但是数据报文的接收还是需要一个接一个地来,从以上的示例代码和其调试过程我们都可以明确看到这一点。
2)在 Linux 系统中,可以创建的线程是有限的。可以通过 cat /proc/sys/kernel/threads-max命令查看可以创建的最大线程数。当然这个值可以更改,但是参与调度的线程数量越大, CPU 用在线程间切换所需的时间也就越长,用来处理真正业务的资源也就越少。CPU 线程状态间切换的性能消耗是非常巨大的,后文我们会对这个描述给出相应的实例以便将这个感性的认识具体化,帮助读者真正认识线程间状态切换的性能代价 。
3)创建一个线程是有较大的资源消耗的 。 例如 NM 创建一个线程时,即使这个线程不做任何工作,JVM都会分配一个独立线程技空间(不同 JDK 版本默认的大小不一样〉 。虽然它可以通过“-Xss ”参数进行大小调整,但这不影响 CPU 一级、 二次缓存中的数据出现线程数据的换入/换出 。
总结:
阻塞模型的问题关键不在于是否使用了多线程(包括线程池)处理并发请求,而在于 accept()、 read()的操作点都被阻塞了 。
完
网络I/O模型--02阻塞模式(多线程)的更多相关文章
- 网络I/O模型--01阻塞模式(普通)
很长一段时间内,大多数网络通信方式都是阻塞模式,即: · 客户端 向服务器端发出请求后,客户端会一直处于等待状态(不会再做其他事情),直到服务器端返回结果或者网络出现问题 . · 服务器端同样如此,当 ...
- Socket 阻塞模式和非阻塞模式
阻塞I/O模型: 简介:进程会一直阻塞,直到数据拷贝 完成 应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好. 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返 ...
- 网络IO模型与Reactor模式
一.三种网络IO模型: 分类: BIO 同步的.阻塞式 IO NIO 同步的.非阻塞式 IO AIO 异步非阻塞式 IO 阻塞和同步的概念: 阻塞:若读写未完成,调用读写的线程一直等待 非阻塞:若读写 ...
- 简明网络I/O模型---同步异步阻塞非阻塞之惑
转自:http://www.jianshu.com/p/55eb83d60ab1 网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之 ...
- 网络I/O模型---同步异步阻塞非阻塞之惑
网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之改变.C10k的问题,让工程师们需要思考服务的性能与应用的并发能力. 网络应用需要 ...
- UNIX网络编程读书笔记:I/O模型(阻塞、非阻塞、I/O复用、信号驱动、异步)
I/O模型 UNIX下可用的5种I/O模型: (1)阻塞I/O (2)非阻塞I/O (3)I/O复用(select和poll) (4)信号驱动I/O(SIGIO) (5)异步I/O 对于一个套接口上的 ...
- 网络IO模型 非阻塞IO模型
网络IO模型 非阻塞IO模型 同步 一件事做完后再做另一件事情 异步 同时做多件事情 相对论 多线程 多进程 协程 异步的程序 宏观角度:异步 并发聊天 阻塞IO 阻塞IO的问题 一旦阻塞就不能做其他 ...
- TCP同步与异步及阻塞模式,多线程+阻塞模式,非阻塞模式简单介绍
首先我简单介绍一下同步TCP编程 与异步TCP编程. 在服务端我们通常用一个TcpListener来监听一个IP和端口.客户端来一个请求的连接,在服务端可以用同步的方式来接收,也可以用异步的方式去接收 ...
- 转:PHP中实现非阻塞模式
原文来自于:http://blog.csdn.net/linvo/article/details/5466046 程序非阻塞模式,这里也可以理解成并发.而并发又暂且可以分为网络请求并发 和本地并发 . ...
随机推荐
- 语义分割Semantic Segmentation研究综述
语义分割和实例分割概念 语义分割:对图像中的每个像素都划分出对应的类别,实现像素级别的分类. 实例分割:目标是进行像素级别的分类,而且在具体类别的基础上区别不同的实例. 语义分割(Semantic S ...
- start with connect by prior
start with connect by prior的使用: select … from tablename start with 条件1 connect by 条件2 where 条件3; sta ...
- QMYSQL driver not loaded
QT5 连接 QMYSQL 数据库时出现错误:QMYSQL driver not loaded. 解决方法如图:(图中使用指令:ldd libqsqlmysql.so) 从结果图显示中:libmysq ...
- Python -- 网络编程 -- Socket简单网络通信
Qt如果多线程的话,似乎会出BUG 1.服务端(server.py) import sys, socket, threading import binascii from PyQt4 import Q ...
- javascript数组原型方法
1.javascript数组原型方法. <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- C#的进度条透明的情况(穿透问题)
如图: 很明显,可以看到透过进度条的框框可以看到下面的软件界面, 之前出现这种情况是因为pictureBox和panel层级之间的关系造成的, 没想到这次的原因居然不是这样,而是因为少了backCol ...
- 面试:C/C++常见库函数实现
1. void *mymemcpy(void *dest, const void* src, size_t n): 内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个 ...
- rails中params[:id]与params["id"]分析
写这个帖子的缘由是因为在页面参数传到rails的controller时用params[:]和params[""]都可以取到值: [1] pry(#<BooksControll ...
- rails 国际化、validate校验、flash提示
1.Rails的国际化 根据特定的locale信息,提取相应的内容 通过config/environment.rb,指定应用的转换文件 config.i18n.load_path +=Dir[Ra ...
- Java 和 JSP 实现网站访问量统计 (刷新过滤)
java 和 JSP 实现的统计网站访问量,不需要数据库,将数据存储在 指定位置的 txt 文件中,代码块分为两部分 首先, java 部分: import java.io.File; import ...