当服务器收到客户端 X 的请求后(读取到所有请求数据后),将这个请求送入一个独立线程进行处理,然后主线程继续接收客户端 Y 的请求。
客户端一侧也可以使用一个子线程和服务器端进行通信。这样客户端主线程的其他工作就不受影响了,当服务器端有响应信息时再由这个子线程通过监听模式/观察模式或者类似的其他设计模式通知主线程。

服务端

  1. package testBlockSocket;
  2.  
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7.  
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10.  
  11. // 通过多线程的方式处理socket的连接
  12. public class SocketServer2MiltiThread {
  13. private final static Logger LOGGER = LoggerFactory.getLogger(SocketServer2MiltiThread.class);
  14.  
  15. public static void main(String[] args) throws Exception {
  16. ServerSocket serverSocket = new ServerSocket(8888);
  17. try {
  18. while (true) {
  19. Socket socket = serverSocket.accept();
  20. // 业务处理过程可以交给一个线程,不过线程的创建很耗资源
  21. // 最终改变不了, accept () 只能在被阻塞的情况一个一个接收 Socket
  22. SocketServerThread socketServerThread = new SocketServerThread(socket);
  23. Thread thread = new Thread(socketServerThread);
  24. thread.start();
  25. }
  26. } catch (Exception e) {
  27. SocketServer2MiltiThread.LOGGER.error(e.getMessage(), e);
  28. } finally {
  29. if (serverSocket != null) {
  30. serverSocket.close();
  31. // 当然 , 接收到客户端的 Socket 后 , 业务的处理过程可以交给一个线程来做
  32. }
  33. }
  34. }
  35.  
  36. }
  37.  
  38. class SocketServerThread implements Runnable {
  39. private final static Logger LOGGER = LoggerFactory.getLogger(SocketServerThread.class);
  40.  
  41. private Socket socket;
  42.  
  43. public SocketServerThread(Socket socket) {
  44. this.socket = socket;
  45. }
  46.  
  47. @Override
  48. public void run() {
  49. InputStream inputStream = null;
  50. OutputStream outputStream = null;
  51. try {
  52. // 下面我们收取信息
  53. inputStream = socket.getInputStream();
  54. outputStream = socket.getOutputStream();
  55. Integer sourcePort = socket.getPort();
  56. int maxLen = 1024;
  57. byte[] contextBytes = new byte[maxLen];
  58. // 同样无法改变 read 方法被阻塞,直到操作系统有数据准备好的现象
  59. int realLen = inputStream.read(contextBytes, 0, maxLen);
  60. String message = new String(contextBytes, 0, realLen);
  61. LOGGER.info("服务器收到来自于端曰 :" + sourcePort + " 的信息:" + message);
  62. // 下面开始发送响应信息
  63. outputStream.write("因发响应信息 !".getBytes());
  64. } catch (Exception e) {
  65. SocketServerThread.LOGGER.error(e.getMessage(), e);
  66. } finally {
  67. // 试图关闭连接
  68. try {
  69. inputStream.close();
  70. outputStream.close();
  71. socket.close();
  72. } catch (Exception e) {
  73. SocketServerThread.LOGGER.error(e.getMessage(), e);
  74. }
  75. }
  76. }
  77.  
  78. }

1)虽然在服务器端,接收到数据后的处理交给了 一个独立线程进行,但是操作系 统通知accept()的方式还是单个线程运行的 。 也就是说,实际上是服务器接收到数据报文后的“业务处理过程”可以应用多线程技术,但是数据报文的接收还是需要一个接一个地来,从以上的示例代码和其调试过程我们都可以明确看到这一点。
          2)在 Linux 系统中,可以创建的线程是有限的。可以通过 cat /proc/sys/kernel/threads-max命令查看可以创建的最大线程数。当然这个值可以更改,但是参与调度的线程数量越大, CPU 用在线程间切换所需的时间也就越长,用来处理真正业务的资源也就越少。CPU 线程状态间切换的性能消耗是非常巨大的,后文我们会对这个描述给出相应的实例以便将这个感性的认识具体化,帮助读者真正认识线程间状态切换的性能代价 。
         3)创建一个线程是有较大的资源消耗的 。 例如 NM 创建一个线程时,即使这个线程不做任何工作,JVM都会分配一个独立线程技空间(不同 JDK 版本默认的大小不一样〉 。虽然它可以通过“-Xss ”参数进行大小调整,但这不影响 CPU 一级、 二次缓存中的数据出现线程数据的换入/换出 。

总结:

阻塞模型的问题关键不在于是否使用了多线程(包括线程池)处理并发请求,而在于 accept()、 read()的操作点都被阻塞了 。

网络I/O模型--02阻塞模式(多线程)的更多相关文章

  1. 网络I/O模型--01阻塞模式(普通)

    很长一段时间内,大多数网络通信方式都是阻塞模式,即: · 客户端 向服务器端发出请求后,客户端会一直处于等待状态(不会再做其他事情),直到服务器端返回结果或者网络出现问题 . · 服务器端同样如此,当 ...

  2. Socket 阻塞模式和非阻塞模式

    阻塞I/O模型: 简介:进程会一直阻塞,直到数据拷贝 完成 应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好. 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返 ...

  3. 网络IO模型与Reactor模式

    一.三种网络IO模型: 分类: BIO 同步的.阻塞式 IO NIO 同步的.非阻塞式 IO AIO 异步非阻塞式 IO 阻塞和同步的概念: 阻塞:若读写未完成,调用读写的线程一直等待 非阻塞:若读写 ...

  4. 简明网络I/O模型---同步异步阻塞非阻塞之惑

    转自:http://www.jianshu.com/p/55eb83d60ab1 网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之 ...

  5. 网络I/O模型---同步异步阻塞非阻塞之惑

    网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之改变.C10k的问题,让工程师们需要思考服务的性能与应用的并发能力. 网络应用需要 ...

  6. 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 对于一个套接口上的 ...

  7. 网络IO模型 非阻塞IO模型

    网络IO模型 非阻塞IO模型 同步 一件事做完后再做另一件事情 异步 同时做多件事情 相对论 多线程 多进程 协程 异步的程序 宏观角度:异步 并发聊天 阻塞IO 阻塞IO的问题 一旦阻塞就不能做其他 ...

  8. TCP同步与异步及阻塞模式,多线程+阻塞模式,非阻塞模式简单介绍

    首先我简单介绍一下同步TCP编程 与异步TCP编程. 在服务端我们通常用一个TcpListener来监听一个IP和端口.客户端来一个请求的连接,在服务端可以用同步的方式来接收,也可以用异步的方式去接收 ...

  9. 转:PHP中实现非阻塞模式

    原文来自于:http://blog.csdn.net/linvo/article/details/5466046 程序非阻塞模式,这里也可以理解成并发.而并发又暂且可以分为网络请求并发 和本地并发 . ...

随机推荐

  1. mysql优化器在统计全表扫描的代价时的方法

    innodb 的聚集索引 的叶子结点 存放的 是 索引值以及数据页的偏移量 那么在计算全表扫描的代价是怎么计算的呢? 我们知道代价 为 cpu代价+io代价 cpu代价 就是 每5条记录比对 计算一个 ...

  2. 剑指offer六十之按之把二叉树打印成多行

    一.题目 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行.二.思路 队列LinkedList完成层序遍历,用end记录每层结点数目 三.代码 import java.util.Arra ...

  3. 搜索类网站记录 && 代理服务器

    搜索类网站记录 && 代理服务器 技巧 1.使用site   我们在搜索的时候,其实不全依赖搜索引擎也是可以的, 比如我们要搜索一个 “中国” ,可以在搜索框输入   中国  site ...

  4. JVM-垃圾收集算法、垃圾收集器、内存分配和收集策略

    对象已死么? 判断一个对象是否存活一般有两种方式: 1.引用计数算法:每个对象都有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1.计数为0时可以回收. 2.可达性分析算法(Reachab ...

  5. Eclipse-查看jar源码乱码问题解决

    步骤1: 在eclipse菜单栏中,Window–>Preferences–>General–>Content types,将JAR Content , Java Class Fil ...

  6. sql server数据行号

    select ROW_NUMBER() over(order by createTime desc) as RowNum,NoticeContent,CreateTime from PTS_Notic ...

  7. c# static用法

    有时候写程序时常常遇到这样的情况:   1.定义了变量和方法不知道什么时候该加上static修饰符. 2.static变量和方法与非static变量和方法有什么区别? 3.在一个类的静态方法里为什么不 ...

  8. Python的Mysql操作

    网上好多的帖子感觉比较老了,而且千篇一律.我到mysql看了一下官网上python驱动的操作,发现与大部分网站说的都不一样. 首先安装的驱动是: pip install mysql-connector ...

  9. plt绘制 2维、3维散点图

    # 3维import numpy as np import matplotlib.pyplot as plt from sklearn.datasets.samples_generator impor ...

  10. C#(Winform)中button的Enable=false和visible的区别

    Enable:可用性 visible:可见性(不是visiable哦,没有这个单词) 如果设置了button或其他控件的Enable为false,还是能够看到控件,只是控件是灰色的,而且点不了: 但设 ...