Netty-使用线程池优化BIO-代码实现

本文介绍了如何使用Netty结合线程池优化传统的BIO模型,以减少资源消耗。首先,背景说明了NIO创建新连接线程的资源浪费问题。接着,文章详细阐述了设计要求,包括构建一个BIO服务器端,监听端口并用线程处理客户端请求。在代码实现部分,主要分为main函数和handler函数,涉及Socket和输入流操作。最后,通过测试程序验证了方案的有效性,通过telnet命令进行交互并观察服务器响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、背景介绍

已知NIO的性质是每有一个新的连接请求就要新建一个线程与之连接,线程的创建对资源的消耗是很大的,可以使用之前学过的池化思想来节省线程资源

2、设计要求

使用BIO模型食记一个服务器端,监听某个端口,当有客户端请求连接时就启动一个线程与之通讯,服务器端可以接收服务器发生的数据
在这里插入图片描述

3、代码实现

代码分为两部分,第一部分是main函数,第二部分是handler函数,需要注意是是涉及到Socke和输入流的一些Java知识点

package BIO;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BIOServer {
   
    public static void main(String[] args) throws IOException {
   
        //线程池:首先创建一个线程池,如果有客户端连接,就创建一个线程与之通讯
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        
        //创建ServerSocket
        ServerSocket serverSocket 
### Spring Boot 中基于线程池的 Server Socket NIO 和 BIO 实现 在 Spring Boot 应用程序中,可以通过配置线程池来管理服务器端套接字(Server Socket)的操作模式。以下是关于如何实现阻塞 I/O(BIO)和非阻塞 I/O(NIO)的方式及其对比。 #### 阻塞 I/O (BIO) 的实现 对于传统的 BIO 方式,每个客户端请求都需要分配一个新的线程来进行处理。这通常通过 `java.net.ServerSocket` 来完成,并结合 Spring 提供的任务执行器(Task Executor)。以下是一个简单的例子: ```java import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.*; import java.net.ServerSocket; import java.net.Socket; @Configuration @EnableAsync public class BioConfig { @Bean public Thread taskExecutor() { return new Thread(() -> { try (ServerSocket serverSocket = new ServerSocket(8080)) { while (true) { Socket clientSocket = serverSocket.accept(); handleClient(clientSocket); } } catch (IOException e) { throw new RuntimeException(e); } }); } private void handleClient(Socket socket) { new Thread(() -> { try ( BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true) ) { String inputLine; while ((inputLine = in.readLine()) != null) { System.out.println("Received: " + inputLine); out.println("Echo: " + inputLine); } } catch (IOException e) { throw new RuntimeException(e); } }).start(); } } ``` 上述代码展示了如何使用多线程模型来支持多个客户端连接[^1]。需要注意的是,在高并发场景下,这种方案可能会导致大量的线程开销以及资源浪费。 --- #### 非阻塞 I/O (NIO) 的实现 相比之下,NIO 使用单个或少量线程即可高效地处理大量并发连接。它依赖于 Java 的 `Selector` 类机制,允许在一个线程上监听多个通道的状态变化。下面提供了一个基本示例: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; @Configuration public class NioConfig { @Bean public Thread nioServerThread() throws IOException { return new Thread(() -> { try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); Selector selector = Selector.open() ) { serverSocketChannel.bind(null /* Bind address */ ); serverSocketChannel.configureBlocking(false); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { int readyChannels = selector.select(); if (readyChannels == 0) continue; Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isAcceptable()) { acceptConnection(serverSocketChannel, selector); } if (key.isReadable()) { readData(key); } keyIterator.remove(); } } } catch (Exception ex) { throw new RuntimeException(ex); } }); } private void acceptConnection(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException { SocketChannel client = serverSocketChannel.accept(); client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ); } private void readData(SelectionKey key) throws IOException { SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = channel.read(buffer); if (bytesRead > 0) { buffer.flip(); byte[] data = new byte[buffer.remaining()]; buffer.get(data); System.out.println("Message received: " + new String(data)); } } } ``` 此方法利用了 NIO 的特性,能够显著减少线程数量并提高系统的吞吐量[^2]。 --- #### 性能比较与适用场景分析 - **BIO** 更适合低并发的应用环境,因为它易于理解和维护。然而,在面对大规模并发访问时,其性能瓶颈明显。 - **NIO** 则更适合高负载的服务端应用开发,尽管其实现复杂度较高,但它提供了更优的时间效率和空间利用率。 为了进一步优化这两种方式下的表现,还可以引入诸如 Netty 这样的框架或者调整底层参数如缓冲区大小 (`SO_RCVBUF`) 等设置[^3][^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值