Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the difference between the three IO models in Java

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article focuses on "what is the difference between the three IO models in Java". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what's the difference between the three IO models in Java?"

1. BIO (Blocking IO, also known as old IO)

Synchronous blocking model, where one client connection corresponds to one processing thread

Each new network connection is assigned to a thread, and each other thread handles its own input and output independently, also known as Connection Per Thread mode

Disadvantages:

1. The read operation in IO code is a blocking operation. If the connection does not read and write data, it will cause thread blocking and waste of resources.

2. If there are too many threads, it will lead to too many server threads and too much pressure, such as C10K problems.

The so-called c10k problem refers to the problem that the server supports thousands of clients at the same time, that is, concurrent 10000 connection

Application scenario: BIO is suitable for architectures with a small and fixed number of connections, which requires high server resources, but the program is simple and easy to understand.

The sample code is as follows:

Bio server

Import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;/** * @ Title:BIO server * @ Author:wangchenggong * @ Date 2021-4-13 9:41 * @ Description * @ Version * / public class SocketServer {public static void main (String [] args) throws IOException {ServerSocket serverSocket = new ServerSocket (9000); while (true) {System.out.println ("waiting for connection.") Socket clientSocket = serverSocket.accept (); System.out.println ("client" + clientSocket.getRemoteSocketAddress () + "connected!") ; handle (clientSocket);}} private static void handle (Socket clientSocket) throws IOException {byte [] bytes = new byte [1024]; int read = clientSocket.getInputStream () .read (bytes); System.out.println ("read client" + clientSocket.getRemoteSocketAddress () + "data finished") If (read! =-1) {System.out.println ("data received from the client:" + new String (bytes, 0, read));} clientSocket.getOutputStream () .write ("HelloClient" .getBytes ()); clientSocket.getOutputStream () .flush ();}}

Bio client

Client of import java.io.IOException;import java.net.Socket;/** * @ Title:BIO * @ Author:wangchenggong * @ Date on 2021-4-13 9:49 * @ Description * @ Version * / public class SocketClient {public static void main (String [] args) throws IOException {Socket socket = new Socket ("localhost", 9000); / / send data socket.getOutputStream (). Write ("HelloServer" .getBytes ()) to the server Socket.getOutputStream () .flush (); System.out.println ("end of sending data to the server"); byte [] bytes = new byte [1024]; / / data returned by the receiving server socket.getInputStream () .read (bytes); System.out.println ("received data from the server:" + new String (bytes)); socket.close () 2. NIO (Non Blocking IO, also intended as new IO)

Synchronous non-blocking, the server implementation mode is that a thread can handle multiple connection requests (connections), the connection requests sent by the client will be registered with the multiplexer selector, and the multiplexer polls to process the IO requests for the connection, which is introduced at the beginning of JDK1.4.

Application scenarios: NIO is suitable for architectures with a large number of connections and short connections (light operation), such as chat server, on-screen comment system, and communication between servers. Programming is relatively complex.

NIO has three core components: Channel (channel), Buffer (buffer), and Selector (multiplexer).

1.channel is similar to a stream. Each channel corresponds to a buffer buffer, and the underlying buffer is an array.

2.channel will register on selector and selector will hand it over to some idle thread to handle according to the occurrence of channel read and write events.

3.NIO 's Buffer and Channel are both readable and writable.

There are two code examples for NIO

NIO without introducing a multiplexer

Server side

Import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.ArrayList;import java.util.Iterator;import java.util.List / * * @ Title:Nio server * @ Author:wangchenggong * @ Date on 2021-4-14 11:04 * @ Description * @ Version * / public class NioServer {/ * Save client connection * / static List channelList = new ArrayList (); public static void main (String [] args) throws IOException {/ / create Nio ServerSocketChannel ServerSocketChannel serverSocket = ServerSocketChannel.open () ServerSocket.socket () .bind (new InetSocketAddress (9000)); / / set ServerSocketChannel to non-blocking serverSocket.configureBlocking (false); System.out.println ("Nio service started successfully") While (true) {/ / non-blocking mode accept method does not block / the non-blocking of NIO is implemented within the operating system, and the underlying accept function of the linux kernel is called SocketChannel socketChannel = serverSocket.accept (); if (socketChannel! = null) {System.out.println ("connected successfully") SocketChannel.configureBlocking (false); channelList.add (socketChannel);} Iterator iterator = channelList.iterator (); while (iterator.hasNext ()) {SocketChannel sc = iterator.next (); ByteBuffer byteBuffer = ByteBuffer.allocate / / the non-blocking mode read method does not block int len = sc.read (byteBuffer); if (len > 0) {System.out.println ("received message:" + new String (byteBuffer.array ();} else if (len = =-1) {iterator.remove () System.out.println ("client disconnect");}

Client

Import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;/** * @ Title:Nio client * @ Author:wangchenggong * @ Date 2021-4-14 11:36 * @ Description * @ Version * / public class NioClient {public static void main (String [] args) throws IOException {SocketChannel socketChannel=SocketChannel.open (new InetSocketAddress ("localhost", 9000)); socketChannel.configureBlocking (false) ByteBuffer writeBuffer=ByteBuffer.wrap ("HelloServer1" .getBytes ()); socketChannel.write (writeBuffer); System.out.println ("end of sending data to server"); writeBuffer=ByteBuffer.wrap ("HelloServer2" .getBytes ()); socketChannel.write (writeBuffer); System.out.println ("end of sending data to server 2"); writeBuffer=ByteBuffer.wrap ("HelloServer3" .getBytes ()) SocketChannel.write (writeBuffer); System.out.println ("end of sending data to server 3");}}

NIO with multiplexer introduced

Server side

Import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.Iterator;import java.util.Set / * * @ Title: the NIO server * @ Author:wangchenggong * @ Date after the introduction of the multiplexer * @ Description * SelectionKey.OP_ACCEPT on 2021-4-14 13:57 * @ Description * server-receives the connection continuation event, indicating that the server is listening for the client connection, and the server can receive the connection * SelectionKey.OP_CONNECT-connection ready event Indicates that the connection between the client and the server has been established successfully * SelectionKey.OP_READ-read ready event indicates that the channel has readable data and can perform read operation (the channel currently has data and can be read) * SelectionKey.OP_WRITE-write ready event indicates that the data can be written to the channel (the channel is currently available for write operations) * * 1. After registering the SelectionKey.OP_READ event in the channel, if the client has write data in the cache, the next poll will isReadable () = true; * * 2. After registering the SelectionKey.OP_WRITE event in the channel, you will find that isWritable () is always true in the current polling thread. If it is not set to another event * @ Version * / public class NioSelectorServer {public static void main (String [] args) throws IOException {/ *, create the server side and register with the multiplexer Let the multiplexer listen for connection events * / / create ServerSocketChannel ServerSocketChannel serverSocket = ServerSocketChannel.open () ServerSocket.socket () .bind (new InetSocketAddress (9000)); / / sets ServerSocketChannel to non-blocking serverSocket.configureBlocking (false); / / opens selector processing channel, that is, creates epoll Selector selector = Selector.open (); / / registers ServerSocketChannel with selector, and selector is interested in serverSocket.register (selector, SelectionKey.OP_ACCEPT) for client accept connection operations System.out.println ("NioSelectorServer service started successfully"); while (true) {/ / blocking waiting for events to be handled selector.select (); / / getting SelectionKey instances of all events registered in selector Set selectionKeys = selector.selectedKeys (); Iterator iterator = selectionKeys.iterator () / / traverse selectionKeys to handle events while (iterator.hasNext ()) {SelectionKey key = iterator.next (); / / if it is an OP_ACCEPT event, connect and register if (key.isAcceptable ()) {ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel () / / accept client connection SocketChannel socketChannel = serverSocketChannel.accept (); socketChannel.configureBlocking (false); / / register SocketChannel with selector, and selector is interested in client read operation (that is, reading messages from client) socketChannel.register (selector, SelectionKey.OP_READ) System.out.println ("client" + socketChannel.getRemoteAddress () + "connection successful!");} else if (key.isReadable ()) {SocketChannel socketChannel = (SocketChannel) key.channel (); ByteBuffer byteBuffer = ByteBuffer.allocate (128); int len = socketChannel.read (byteBuffer) If (len > 0) {System.out.println ("receive a message from the client" + socketChannel.getRemoteAddress () + ", which reads:" + new String (byteBuffer.array ();} else if (len = =-1) {System.out.println ("client disconnect") / / close the client socketChannel.close ();}} / / delete the key for this processing from the event collection to prevent the next select from repeatedly processing iterator.remove () }} / * NioSelectorServer service started successfully * client / 127.0.0.1virtual 57070 connected successfully! * received a message from client / 127.0.0.1virtual 57070 The message content is: HelloServer * client / 127.0.0.1virtual 57121 connected successfully! * received a message from client / 127.0.0.1virtual 57121, the message content is: HelloServer * /}}

Client

Import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Set / * * @ Title: NIO client * @ Author:wangchenggong * @ Date after introducing multiplexer * @ Description * @ Version * on 2021-4-14 14:39 * @ Description * @ Version * / public class NioSelectorClient {public static void main (String [] args) throws IOException {SocketChannel socketChannel = SocketChannel.open (); socketChannel.configureBlocking (false); Selector selector = Selector.open () / / you need to register with the multiplexer before you can connect to the server socketChannel.register (selector, SelectionKey.OP_CONNECT); socketChannel.connect (new InetSocketAddress ("localhost", 9000); while (true) {selector.select (); Set keys = selector.selectedKeys (); Iterator iterator = keys.iterator () While (iterator.hasNext) {SelectionKey key = iterator.next (); iterator.remove (); if (key.isConnectable ()) {SocketChannel sc = (SocketChannel) key.channel () If (sc.finishConnect ()) {System.out.println ("Server connected successfully"); ByteBuffer writeBuffer=ByteBuffer.wrap ("HelloServer" .getBytes ()); sc.write (writeBuffer); System.out.println ("end of sending data to server") } / * * the server connects successfully * sends data to the server end * /}} 3. AIO (Asynchronous IO) is NIO2.0

Asynchronous non-blocking, after the completion of the operating system, the callback informs the server program to start the thread to process, which is generally suitable for applications with a large number of connections and a long connection time.

Application scenarios: AIO is suitable for architectures (applications) with a large number of connections and a long connection time (reoperation), and JDK7 starts to support it.

The reason why the famous asynchronous network communication framework netty abandons AIO is that on Linux systems, the underlying implementation of NIO uses Epoll, while the underlying implementation of AIO still uses Epoll and does not implement AIO very well, so there is no obvious advantage in performance, and it is not easy to be deeply optimized by JDK, and AIO on Linux is not mature enough.

The sample code for AIO is as follows:

Server side

Import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousServerSocketChannel;import java.nio.channels.AsynchronousSocketChannel;import java.nio.channels.CompletionHandler;/** * @ Title:Aio server * @ Author:wangchenggong * @ Date 2021-4-14 17:05 * @ Description * @ Version * / public class AioServer {public static void main (String [] args) throws Exception {final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open () .bind (new InetSocketAddress (9000)) ServerChannel.accept (null, new CompletionHandler () {@ Override public void completed (AsynchronousSocketChannel socketChannel, Object attachment) {try {System.out.println ("2mura -" + Thread.currentThread (). GetName ()); / / receive client connection serverChannel.accept (attachment,this) System.out.println ("client" + socketChannel.getRemoteAddress () + "connected"); ByteBuffer buffer = ByteBuffer.allocate SocketChannel.read (buffer, null, new CompletionHandler () {@ Override public void completed (Integer result, Object attachment) {System.out.println ("3mura -" + Thread.currentThread () .getName ()) The / / flip method switches the Buffer from write mode to read mode / / if not, it is read from the end of the file, and of course all the characters read are byte=0 characters. Through buffer.flip (); this statement, you can change the current position of buffer to the first location of the buffer buffer: buffer.flip (); System.out.println (new String (buffer.array (), 0, result)); socketChannel.write (ByteBuffer.wrap ("hello Aio Client!" .getBytes () } @ Override public void failed (Throwable exc, Object attachment) {exc.printStackTrace ();}});} catch (Exception e) {e.printStackTrace () } @ Override public void failed (Throwable exc, Object attachment) {}}); System.out.println ("1--main" + Thread.currentThread () .getName ()); Thread.sleep (Integer.MAX_VALUE) } / * * 1--mainmain * 2--Thread-9 * client / 127.0.0.1 3--Thread-8 54821 connected * 3--Thread-8 * client! * 2--Thread-9 * client / 127.0.0.1 hello AIO server 54942 connected * 3--Thread-7 * client! * /}

Client

Import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousSocketChannel;/** * @ Title:Aio client * @ Author:wangchenggong * @ Date 2021-4-14 16:56 * @ Description * @ Version * / public class AioClient {public static void main (String [] args) throws Exception {/ / create Aio client AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open (); socketChannel.connect (new InetSocketAddress ("localhost", 9000)) .get () / / send the message socketChannel.write (ByteBuffer.wrap ("hello AIO server!" .getBytes ()); / / receive the message ByteBuffer buffer = ByteBuffer.allocate; Integer len = socketChannel.read (buffer) .get (); if (len! =-1) {/ / the client receives the message: hello Aio Client! System.out.println ("client receives message:" + new String (buffer.array (), 0, len));} at this point, I believe you have a deeper understanding of "what is the difference between the three IO models in Java". You might as well do it in practice! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report