当前位置: 首页 > news >正文

传统网络编程有什么问题

文章目录

  • 多线程版网络编程
    • 客户端
    • MyServerThread
    • 服务端
  • 线程池版的网络编程
    • 客户端
    • MyServerThread
    • 服务端
  • 总结

在这里插入图片描述


传统网络通信中的开发方式及问题

多线程版网络编程

在这里插入图片描述


下面先写一个多线程版网络编程的版本代码:

客户端

public static void main(String[] args) throws IOException {Socket socket;for (int i = 0; i < 5; i++) {socket = new Socket("127.0.0.1", 8899);PrintWriter printWriter = new PrintWriter(socket.getOutputStream());printWriter.write("hello , 我是客户端 " + i);printWriter.flush();socket.close();}
}

MyServerThread

public class MyServerThread implements Runnable {private Socket socket;public MyServerThread(Socket socket){this.socket = socket;}@Overridepublic void run() {BufferedReader bufferedReader = null;try {bufferedReader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));while( true ){String s = bufferedReader.readLine();if( s == null ){break;}System.out.println(Thread.currentThread().getName() + "  "+s);}} catch (IOException e) {e.printStackTrace();} finally {try {if (socket != null && !socket.isClosed()) {socket.close();}} catch (IOException e) {e.printStackTrace();}}}
}

服务端

public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8899);Socket socket = null;while (true){socket = serverSocket.accept();new Thread( new MyServerThread(socket) ).start();}
}

上面的代码存在的问题:

  1. 线程创建开销;
  2. 内存占用高,不能无限制的创建线程;
  3. CPU使用率高;

线程池版的网络编程

客户端

public static void main(String[] args) throws IOException {Socket socket;for (int i = 0; i < 30; i++) {socket = new Socket("127.0.0.1", 8899);PrintWriter printWriter = new PrintWriter(socket.getOutputStream());printWriter.write("hello , 我是客户端 " + i);printWriter.flush();socket.close();}
}

MyServerThread

public class MyServerThread implements Runnable {private Socket socket;public MyServerThread(Socket socket){this.socket = socket;}@Overridepublic void run() {BufferedReader bufferedReader = null;try {bufferedReader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));while( true ){String s = bufferedReader.readLine();if( s != null ){System.out.println(Thread.currentThread().getName() + "  "+s);}}} catch (IOException e) {e.printStackTrace();} finally {try {if (socket != null && !socket.isClosed()) {socket.close();}} catch (IOException e) {e.printStackTrace();}}}
}

服务端

public class Server {static ThreadPoolExecutor threadPoolExecutor;//	线程池static {threadPoolExecutor = new ThreadPoolExecutor(5, 10, 120,TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20));}public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8899);Socket socket = null;while (true){socket = serverSocket.accept();//new Thread( new MyServerThread(socket) ).start();threadPoolExecutor.execute( new MyServerThread(socket) );}}
}

上面的代码是以线程池的方式解决之前的问题. 解决了线程开销问题和CPU占用率高的问题.

新的问题: 因为阻塞, 造成有限线程资源的浪费;


总结

与 Java NIO(New Input/Output)相比,传统网络编程(主要指的是基于阻塞 I/O 的模型)有一些明显的问题和局限性:

  1. 线程管理开销
    传统网络编程: 每个客户端连接通常会分配一个独立的线程。对于高并发场景,这种方法会导致线程数量急剧增加,从而增加线程上下文切换的开销和系统资源消耗。
    NIO: 通过使用选择器(Selectors)和非阻塞 I/O,可以用少量的线程处理大量的连接,显著降低了线程管理的开销。
  2. 阻塞 I/O
    传统网络编程: 使用阻塞 I/O 模型时,线程在等待数据读写时会被阻塞,这可能导致资源的浪费和响应时间的增加。
    NIO: 支持非阻塞 I/O 模型,使线程可以在等待 I/O 操作完成的同时执行其他任务,从而提高了效率。
  3. 扩展性
    传统网络编程: 处理大量并发连接时,系统可能会遇到性能瓶颈和资源限制,特别是在处理大量 I/O 操作时。
    NIO: 设计用于支持大规模的网络应用,可以高效地管理和调度大量的连接,具有更好的扩展性。
  4. 资源利用效率
    传统网络编程: 在处理高并发连接时,由于线程阻塞和切换的开销,系统资源(如 CPU 和内存)的利用效率较低。
    NIO: 通过减少线程的数量和避免线程阻塞,提高了系统资源的利用效率。
  5. 编程复杂性
    传统网络编程: 编写和管理基于阻塞 I/O 的网络代码相对简单,但在高并发场景下可能难以管理和扩展。
    NIO: 虽然提供了更高效的 I/O 模型,但其 API 更复杂,需要开发者理解选择器、通道和缓冲区的工作机制,增加了编程难度。
  6. 错误处理
    传统网络编程: 错误处理通常较为简单,但在处理大量并发连接时,可能会遇到性能瓶颈和资源耗尽问题。
    NIO: 错误处理可能更为复杂,需要处理各种异步事件和状态,增加了调试和维护的难度。
  7. 适应性
    传统网络编程: 在设计上可能不容易适应高并发和大规模数据传输的需求。
    NIO: 设计目标包括高并发和高性能,能够更好地适应现代网络应用的需求。

传统网络编程在处理高并发和大规模应用时通常面临性能瓶颈和资源管理问题,而 NIO 通过非阻塞 I/O 和选择器机制提供了更高效的解决方案。虽然 NIO 的 API 更复杂,但在高负载和高性能需求的场景下,它能够显著改善传统阻塞 I/O 的不足。




相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 前端开发工程师面试整理-ES6+的新特性
  • 测试资料4444
  • 获取当前路由器的外网IP(WAN IP)
  • 精粹CSS伪类::enabled与:disabled的优雅应用
  • Python中网络请求中Retry策略实现方式例子解析
  • i.MX6裸机开发(9):CCM时钟控制模块
  • 【注解】@JsonProperty 详解
  • 流媒体服务器二 3学习 librtmp 库的配置使用
  • 华大flash EFM使用(一)
  • 《重温JavaScript五子棋小游戏》
  • ArcGIS热点分析 (Getis-Ord Gi*)——基于地级市尺度的七普人口普查数据的热点与冷点分析
  • Leetcode-day28-贪心算法
  • 打印样式的艺术:用CSS @media 规则优化页面输出
  • 网络udp及ipc内存共享
  • FPGA工程师成长路线(持续更新ing,欢迎补充)
  • 自己简单写的 事件订阅机制
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • docker python 配置
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • IndexedDB
  • linux安装openssl、swoole等扩展的具体步骤
  • storm drpc实例
  • use Google search engine
  • Zsh 开发指南(第十四篇 文件读写)
  • 包装类对象
  • 程序员最讨厌的9句话,你可有补充?
  • 多线程事务回滚
  • 分布式熔断降级平台aegis
  • 聚簇索引和非聚簇索引
  • 前端路由实现-history
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 实战|智能家居行业移动应用性能分析
  • 我的面试准备过程--容器(更新中)
  • 硬币翻转问题,区间操作
  • 由插件封装引出的一丢丢思考
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • 组复制官方翻译九、Group Replication Technical Details
  • ​​​【收录 Hello 算法】9.4 小结
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​什么是bug?bug的源头在哪里?
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • (备忘)Java Map 遍历
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (一)Linux+Windows下安装ffmpeg
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转载)hibernate缓存
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .DFS.
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务