由于应用程序级别并没有使用多线程技术,这就导致了应用程序只能一个一个地对Socket 套接字进行处理。这个 Socket 套接宇没有处理完,就没法处理下一个 Socket 套接字 。针对这个 问题还是可以进行改进的:让应用程序层面上各个 Socket 套接字的处理相互不影响 。

服务端代码

package testBlockSocket;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; //通过加入线程的概念,让 Socket Server 能够在应用层面
//通过非阻塞的方式同时处理多个 Socket 套接字
public class SocketServer4AllTimeoutAndMultiThread {
private final static Logger LOGGER = LoggerFactory.getLogger(SocketServer4AllTimeoutAndMultiThread.class);
private static Object xWait = new Object(); public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
serverSocket.setSoTimeout(100);
try {
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (SocketTimeoutException el) {
// ===================
// 执行到这里,说明本次 accept()方法没有接收到任何 TCP 连接主线程在这里就可以做一些事情,记为 x
// ==================
synchronized (SocketServer4AllTimeoutAndMultiThread.xWait) {
LOGGER.info("这次没有接收到 TCP 连接,等待10 毫秒,模拟事件x 的处理时间 ");
SocketServer4AllTimeoutAndMultiThread.xWait.wait(10);
}
continue;
}
// 业务处理过程可以交给一个线程(这里可以使用线程池)
// 注意 , 线程的创建过程是很耗资源和时间的 // 最终改变不了 accept ( )方法只能一个一个地接收 Socket 连接的情况
SocketServerThreadWithTimeOut socketServerThread = new SocketServerThreadWithTimeOut(socket);
new Thread(socketServerThread).start();
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
} finally {
if (serverSocket != null) {
serverSocket.close();
}
}
}
} // 当然,接收到客户端的 Socket 后,业务的处理过程可以交给一个线程来做
class SocketServerThreadWithTimeOut implements Runnable { private final static Logger LOGGER = LoggerFactory.getLogger(SocketServerThreadWithTimeOut.class);
private Socket socket; public SocketServerThreadWithTimeOut(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 = 2048;
byte[] contextBytes = new byte[maxLen];
int realLen;
StringBuffer message = new StringBuffer();
// 下面我们收取信息
this.socket.setSoTimeout(10);
BIORead: while (true) {
try {
while ((realLen = inputStream.read(contextBytes, 0, maxLen)) != -1) {
message.append(new String(contextBytes, 0, realLen));
// 我们同样假设读取到"over"关键字,表示业务内容传输完成
if (message.indexOf("over") != -1) {
break BIORead;
}
}
} catch (SocketTimeoutException e2) {
// =================
// 执行到这里,说明本次 read ()方法没有接收到任何数据流主线程在这里又可以做一些事情,记为 Y
// =================
LOGGER.info("这次没有接收到任务数据报文,等待 10 ~盖秒 ,模拟事件 Y 的处理时间 ");
continue;
}
}
// 下面打印信息
Long threadId = Thread.currentThread().getId();
SocketServerThreadWithTimeOut.LOGGER.info("服务器(线程 :" + threadId + ")收到来自于端口 :" + sourcePort + "的信息: " + message);
// 下面开始发送信息
outputStream.write("回发响应信息:".getBytes());
// 关闭 in 和 out 对象
inputStream.close();
outputStream.close();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
}

引入了多线程技术后, I/O的处理吞吐量有了提高(实际上并不显著) ,因为 acceptO方法为“同步”工作的情况依然存在 。

网络I/O模型--04非阻塞模式(解除accept()、 read()方法阻塞)的基础上加入多线程技术的更多相关文章

  1. 网络I/O模型--03非阻塞模式(ServerSocket与Socket的超时处理)--解除accept()、 read()方法阻塞

    对于阻塞方式的一种改进是在应用程序层面上将 “一直等待 ”的状态主动打开: 这种模式下,应用程序的线程不再一直等待操作系统的 I/O状态,而是在等待一段时间后就解除阻塞.如果没有得到想要的结果,则再次 ...

  2. ubuntu16.04 源码安装Python3.7 (可以在此基础上安装Tensorflow) (确保Tensorflow计算框架与系统的彻底隔离)

    Python3.7 源码下载: https://www.python.org/downloads/release/python-370/ 解压源码: tar -zxvf Python-3.7.0.tg ...

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

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

  4. socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto

    socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...

  5. thinkphp并发 阻塞模式与非阻塞模式

    结构代码 public function index(){ $fp = fopen("lock.txt", "w+"); if(flock($fp,LOCK_E ...

  6. stm32中阻塞模式和非阻塞模式 in blocking mode 与 in non-blocking mode区别

    阻塞模式和非阻塞模式...... 我的理解是:阻塞模式就像是一个延时函数,当这个函数没处理完那么,所有的按照流程需要执行的代码都不会被执行,要等到这个延时完成,类似 平时看书上写的LED灯闪烁,用的d ...

  7. Python Socket单线程+阻塞模式

    Python之旅]第五篇(二):Python Socket单线程+阻塞模式 python Socket单线程 Socket阻塞模式 串行发送 摘要:  前面第五篇(一)中的一个Socket例子其实就是 ...

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

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

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

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

随机推荐

  1. JavaScript 闭包解决计数器问题

    JavaScript 闭包解决计数器问题 var add = (function () { var counter = 0; return function () {return counter += ...

  2. mysql互为主从实战设置详解及自动化备份(Centos7.2)

    mysql互为主从实战设置详解(Centos7.2) 第一步:mysql配置  my.cnf配置 服务器1 (10.89.10.90) [mysqld]  server-id=1  log-bin=/ ...

  3. SPSS学习系列之SPSS Modeler怎么修改默认的内存大小(图文详解)

    不多说,直接上干货! 问题来源: 如果你的电脑内存配置比较低的话,会随着数据量增加(尤其是大数据),带不起的情况很有可能发生,会出现一些内存报错... ... 解决办法: 打开“工具”,在modele ...

  4. PMP备考指南之第二章:项目运作环境

    本文已同步至 GitHub/Gitee/公众号,感兴趣的同学帮忙点波关注~ 第二章:项目运作环境 1. 事业环境因素.组织过程资产 事业环境因素 Enterprise Environmental Fa ...

  5. android学习-进程/线程管理-完整

    我们知道,应用程序的主入口都是main函数--"它是一切事物的起源" main函数工作也是千篇一律的, 初始化 比如ui的初始化,向系统申请资源等. 进入死循环 再循环中处理各种事 ...

  6. 堆排序详解以及java实现

    前言 临近毕业,开始找工作,近期一直在看算法导论(CLRS)同时各种刷题.希望以后有时间把所有学习心得和刷题心得记录下来. 堆 堆排序和合并排序一样,是一种时间复杂度为O(nlgn)的算法,同时和插入 ...

  7. 面试题43:计算多少种译码方式(decode-ways)

    这道题是非常典型的DP问题.按照DP的套路,关键是讨论出递推表达式,遍历过程中针对当前字符是否为'0'以及前一个字符为'0',分类讨论得出到目前字符为止最多有多少种译码方式?理清了递推表达式,代码是很 ...

  8. 微信公众号H5支付

    微信支付说明1.统一下单接口 统一支付接口: url: https://api.mch.weixin.qq.com/pay/unifiedorder 目的:通过此接口来创建预支付订单,获取订单支付需要 ...

  9. [CQOI 2018]异或序列&[Codeforces 617E]XOR and Favorite Number

    Description 题库链接1 题库链接2 已知一个长度为 \(n\) 的整数数列 \(a_1,a_2,\cdots,a_n\) ,给定查询参数 \(l,r\) ,问在 \([l,r]\) 区间内 ...

  10. 二维码之qrencode生成(带logo)

    从github下载的qrencode没有QRCodeGenerator文件,需要引入 // // QR Code Generator - generates UIImage from NSString ...