.BIO a concept of the NIO and AIO
BIO is a synchronous blocking IO
NIO is synchronous non-blocking IO (NIO1.0, JDK1.4)
AIO is asynchronous nonblocking IO (NIO2.0, JDK1.7)
Two .BIO simple analysis
1. Simple analysis
BIO is blocking IO, because accept and read will block. So single-threaded BIO is unable to handle concurrency.
2. Case
Server:
class public BioServer {
public static void main (String [] args) throws IOException {
the ServerSocket = new new serverSocket the ServerSocket ();
ServerSocket.bind (the InetSocketAddress new new ( "127.0.0.1", 9999 ));
byte [] = new new byte B [ 1024 ]; the StringBuilder new new SB = the StringBuilder (); System.out.println ( "waiting for connection in the correct service ......" ); the Socket socketAccept = serverSocket.accept (); // this will block System.out. println ( "client connection successful" ); the while (to true ) {System.out.println ( "wait message ......" );. socketAccept.getInputStream int = Read () Read (B); // here it will block System.out.println ( "total read" + read + "bytes" ); String = new new STRString (b); sb.append (str ); System.out.println ( " data content is read:" + SB);}}}
Client:
public class BioClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket();
Scanner scanner = new Scanner(System.in);
socket.connect(new InetSocketAddress("127.0.0.1",9999));
while(true){ System.out.println("请输入内容"); String next = scanner.next(); socket.getOutputStream().write(next.getBytes()); } } }
Tests are as follows:
BIO under 3. Multithreading
BIO is multithreaded concurrent treatment, but frequent create threads, and the number of threads running (even if you can use the thread pool thread limit destroying threads is undoubtedly a very resource-intensive, but when massive concurrency, the efficiency of BIO way compared to NIO or too low)
Here is a multithreaded BIO Case:
Server:
public class BioServerMultiThread { public static void main (String [] args) throws IOException { the ServerSocket serverSocket = new new the ServerSocket (); ServerSocket.bind ( new new the InetSocketAddress ( "127.0.0.1", 9999 )); System.out.println ( "Service correct waiting for connection ...... " ); the while ( to true ) { the Socket socketAccept = serverSocket.accept (); // this will block System.out.println (" client connection success " ); new new the Thread ( new new the Runnable () { @Override public void run() { try{ System.out.println("等待消息......"); String msg = ""; while (true){ byte[] b = new byte[1024]; int len = socketAccept.getInputStream().read(b); if (len < 0){ continue; } msg = new String(b,0,len); System.out.println(msg); } }catch (Exception e){ e.printStackTrace(); } } }).start(); } } }
The client (create multiple clients, the same code):
public class BioClient1 { public static void main(String[] args) throws IOException { Socket socket = new Socket(); Scanner scanner = new Scanner(System.in); socket.connect(new InetSocketAddress("127.0.0.1",9999)); String className = "这是来自"+Thread.currentThread().getStackTrace()[1].getClassName()+"的消息"; while(true){ System.out.println("请输入内容"); String next = scanner.next(); socket.getOutputStream().write(className.getBytes()); socket.getOutputStream().write(next.getBytes()); } } }
Tests are as follows:
Three .NIO simple analysis
NIO is non-blocking IO, reason is that the data is ready, the notification by the selector to the server, but before the data is ready, the server without waiting.
1. Buffer
BIO In operation, all data is in the form of flow operation, in the NIO, the buffers are used to operate.
NIO Buffer is the Buffer class, it is an abstract class under java.nio package, you can view the details of the JDK API documentation, such as the following figure
Open Buffer class, can be seen below (with which the method can view JDK documentation)
2. Direct and indirect buffer buffer
Direct buffer refers to a buffer to establish in physical memory, the method established by allocateDirect (high efficiency, but not safe)
Indirect buffer refers to a buffer built on the JVM, established by allocate method (low efficiency, but safety)
3. Pipeline
NIO the bridge conduit is transmitting data, which is an interface in java.nio package, API documentation which For details refer to the JDK, for example, FIG.
4. Use the file copy are two ways to achieve NIO Case
Direct way buffer:
@Test public void test1() throws IOException { long statTime=System.currentTimeMillis(); //创建管道 FileChannel inChannel= FileChannel.open(Paths.get("E://test/aaa.txt"), StandardOpenOption.READ); FileChannel outChannel= FileChannel.open(Paths.get("E://test/bbb.txt"), StandardOpenOption.READ,StandardOpenOption.WRITE, StandardOpenOption.CREATE); //定义映射文件 MappedByteBuffer inMappedByte = inChannel.map(FileChannel.MapMode.READ_ONLY,0, inChannel.size()); MappedByteBuffer outMappedByte = outChannel.map(FileChannel.MapMode.READ_WRITE,0, inChannel.size()); //直接对缓冲区操作 byte[] dsf=new byte[inMappedByte.limit()]; inMappedByte.get(dsf); outMappedByte.put(dsf); inChannel.close(); outChannel.close(); long endTime=System.currentTimeMillis(); System.out.println("操作直接缓冲区耗时时间:"+(endTime-statTime)); }
非直接缓冲区的方式:
@Test public void test2() throws IOException { long statTime=System.currentTimeMillis(); // 读入流 FileInputStream fst = new FileInputStream("E://test/bbb.txt"); // 写入流 FileOutputStream fos = new FileOutputStream("E://test/ccc.txt"); // 创建通道 FileChannel inChannel = fst.getChannel(); FileChannel outChannel = fos.getChannel(); // 分配指定大小缓冲区 ByteBuffer buf = ByteBuffer.allocate(1024); while (inChannel.read(buf) != -1) { // 开启读取模式 buf.flip(); // 将数据写入到通道中 outChannel.write(buf); buf.clear(); } // 关闭通道 、关闭连接 inChannel.close(); outChannel.close(); fos.close(); fst.close(); long endTime=System.currentTimeMillis(); System.out.println("操作非直接缓冲区耗时时间:"+(endTime-statTime)); }
5.选择器(Selector)
它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。如此可以实现单线程管理多个channels,也就是可以管理多个网络链接。使用Selector的好处在于: 使用更少的线程来就可以来处理通道了, 相比使用多个线程,避免了线程上下文切换带来的开销。详细用法可以参考JDK的API文档
四.AIO简单分析
AIO(NIO2.0)和 NIO的主要区别是前者是异步的,而后者是同步的。
与NIO不同,当进行读写操作时,AIO只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。 即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。