企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### 介绍 ![](https://img.kancloud.cn/37/14/3714356aa8b6fe52b25d0da61f8d9108_670x239.png) ### 同步IO之BlockingIO ![](https://box.kancloud.cn/56ff8ce655e799951d2d88150283f200_552x331.png) 如上图所示,用户进程process在Blocking IO读recvfrom操作的两个阶段都是等待的。在数据没准备好的时候,process原地等待kernel准备数据。kernel准备好数据后,process继续等待kernel将数据copy到自己的buffer。在kernel完成数据的copy后process才会从recvfrom系统调用中返回 ### 同步阻塞式I/O ``` public class SocketServer { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(8999); while (true) { Socket socket = server.accept(); new Thread(new ChannelSocker(socket)).start(); } } static class ChannelSocker implements Runnable { private Socket socket; public ChannelSocker(Socket socket) { this.socket = socket; } @Override public void run() { StringBuffer res = new StringBuffer(); try (InputStream inputStream = socket.getInputStream(); InputStreamReader reader = new InputStreamReader(inputStream); BufferedReader read = new BufferedReader(reader);) { String line = read.readLine(); while (line != null) { res.append(line); line = read.readLine(); } } catch (IOException e) { e.printStackTrace(); } finally { System.err.println("接收到消息" + res.toString()); } } } } ``` 阻塞型I/O,主要阻塞在两个地方: 1. 在调用InutStream.read方法是阻塞的,它会一直等到数据到来时(或超时)才会返回; 2. 在调用ServerSocket.accept方法时,也会一直阻塞到有客户端连接才会返回; ### setSoTimeout serverSocket.setSoTimeout\(3000\); \#\# soTimeout将accept阻塞3秒 Socket socket = serverSocket.accept\(\); ``` try (ServerSocket serverSocket = new ServerSocket(8089)){ serverSocket.setSoTimeout(3000); Socket socket = serverSocket.accept(); System.err.println("finished"); } catch (Exception e) { e.printStackTrace(); } System.err.println("end==>"); ``` ### SO\_RCVBUF SO\_RCVBUF选项设置了服务器Socket接受的客户端Socket默认缓冲区大小 ``` try (ServerSocket serverSocket = new ServerSocket(8089)){ serverSocket.setSoTimeout(3000); serverSocket.setReceiveBufferSize(1024); Socket socket = serverSocket.accept(); System.err.println("finished"); } catch (Exception e) { e.printStackTrace(); } System.err.println("end==>"); ``` ### 阻塞模型 ![](https://img.kancloud.cn/ca/11/ca115d9a44177fe9bf1559e1415ef735_700x295.png) ### 阻塞型的I/O存在的问题 InputStream.read\(\)方法在其缓存区未满时会造成阻塞,只有数据填满了缓存区或者客户端关闭了套接字,方法才会返回; BufferedReader创建了缓存区来从套接字中读入数据,但是同样创建了一些字符串存储这些数据,这些String很快变成垃圾需要回收; InputStream 中的read方法用于读取数据,方法有3个重载: * read\(\):从输入流读取下一个数据字节; * read\(byte\[\] b\):从输入流中读取一定数量的字节并将其存储在缓冲区数组b中; * read\(byte\[\] b, int off, int len\):将输入流中最多 len 个数据字节读入字节数组;