Java网络编程基础:从阻塞式I/O到线程池模子

[复制链接]
发表于 2025-7-3 01:21:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
弁言

在Java网络编程的世界中,理解不同的I/O模子对于构建高效的网络应用至关重要。本文将带您从最基础的阻塞式I/O模子出发,渐渐过渡到更高效的线程池模子,资助您建立对Java网络编程的根本认识。
阻塞式I/O模子:连续接一线程

阻塞式I/O是Java网络编程中最简单直观的模子。在这种模子中,服务器为每个客户端连接创建一个专用线程。
SimpleServer实现

  1. public class SimpleServer {
  2.     public static void main(String[] args) throws IOException {
  3.         ServerSocket serverSocket = new ServerSocket(8080);
  4.         System.out.println("服务器启动,监听端口:8080...");
  5.         
  6.         while (true) {
  7.             // 接受客户端连接,这是一个阻塞调用
  8.             Socket clientSocket = serverSocket.accept();
  9.             System.out.println("客户端已连接:" + clientSocket.getInetAddress());
  10.             
  11.             // 为每个客户端创建一个新线程
  12.             new Thread(() -> handleClient(clientSocket)).start();
  13.         }
  14.     }
  15.    
  16.     private static void handleClient(Socket clientSocket) {
  17.         try (
  18.             BufferedReader in = new BufferedReader(
  19.                 new InputStreamReader(clientSocket.getInputStream()));
  20.             PrintWriter out = new PrintWriter(
  21.                 clientSocket.getOutputStream(), true)
  22.         ) {
  23.             String inputLine;
  24.             while ((inputLine = in.readLine()) != null) {
  25.                 System.out.println("收到消息:" + inputLine);
  26.                 out.println("服务器回复:" + inputLine);
  27.             }
  28.         } catch (IOException e) {
  29.             System.out.println("处理客户端连接异常:" + e.getMessage());
  30.         } finally {
  31.             try {
  32.                 clientSocket.close();
  33.             } catch (IOException e) {
  34.                 System.out.println("关闭客户端连接异常:" + e.getMessage());
  35.             }
  36.         }
  37.     }
  38. }
复制代码
阻塞式I/O的优缺点

优点:


  • 实现简单直观
  • 客户端处置处罚逻辑相互独立
  • 得当连接数较少的场景
缺点:


  • 每个连接占用一个线程,资源消耗大
  • 连接数增加时,线程数爆炸
  • 线程上下文切换开销大
  • 不得当高并发场景
线程池模子:资源复用的第一步

为了办理连续接一线程模子的资源浪费问题,线程池模子应运而生。它通过复用有限数量的线程来处置处罚大量连接。
ThreadPoolServer实现

  1. public class ThreadPoolServer {
  2.     public static void main(String[] args) throws IOException {
  3.         // 创建固定大小的线程池
  4.         ExecutorService executor = Executors.newFixedThreadPool(10);
  5.         ServerSocket serverSocket = new ServerSocket(8080);
  6.         System.out.println("线程池服务器启动,监听端口:8080...");
  7.         
  8.         try {
  9.             while (true) {
  10.                 // 接受客户端连接,这仍然是一个阻塞调用
  11.                 Socket clientSocket = serverSocket.accept();
  12.                 System.out.println("客户端已连接:" + clientSocket.getInetAddress());
  13.                
  14.                 // 将客户端处理任务提交到线程池
  15.                 executor.submit(() -> handleClient(clientSocket));
  16.             }
  17.         } finally {
  18.             serverSocket.close();
  19.             executor.shutdown();
  20.         }
  21.     }
  22.    
  23.     private static void handleClient(Socket clientSocket) {
  24.         // 客户端处理逻辑与SimpleServer相同
  25.         try (
  26.             BufferedReader in = new BufferedReader(
  27.                 new InputStreamReader(clientSocket.getInputStream()));
  28.             PrintWriter out = new PrintWriter(
  29.                 clientSocket.getOutputStream(), true)
  30.         ) {
  31.             String inputLine;
  32.             while ((inputLine = in.readLine()) != null) {
  33.                 System.out.println("线程 " + Thread.currentThread().getName()
  34.                     + " 收到消息:" + inputLine);
  35.                 out.println("服务器回复:" + inputLine);
  36.             }
  37.         } catch (IOException e) {
  38.             System.out.println("处理客户端连接异常:" + e.getMessage());
  39.         } finally {
  40.             try {
  41.                 clientSocket.close();
  42.             } catch (IOException e) {
  43.                 System.out.println("关闭客户端连接异常:" + e.getMessage());
  44.             }
  45.         }
  46.     }
  47. }
复制代码
线程池模子的优缺点

优点:


  • 控制并发线程数量,避免线程爆炸
  • 线程复用,淘汰创建和销毁线程的开销
  • 可以根据体系负载调整线程池巨细
  • 得当中等并发场景
缺点:


  • 每个连接的I/O操纵仍然是阻塞的
  • 线程数量仍然与并发连接数相关
  • 高并发场景下仍有性能瓶颈
总结

从阻塞式I/O到线程池模子,我们迈出了Java网络编程优化的第一步。线程池模子通过复用线程资源,在一定水平上提高了服务器的并发处置处罚本领。然而,在面对更高并发的场景时,我们必要探索更先辈的模子,如NIO和Reactor模式,这将在后续文章中详细先容。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表