文章目录
- 前言
- 一、主要模块
- 二、使用步骤
- 1.服务器端
- 2.客户端
- 三、NIO零拷贝(推荐)
- 四、NIO另一种copy
- 总结
前言
NIO是JDK1.4版本带来的功能,区别于以往的BIO编程,同步非阻塞极大的节省资源开销,避免了线程切换和上下文切换带来的资源浪费。
一、主要模块
- Selector:选择器,为事件驱动,做中央调度使用,一个选择器可以注册多个channel;
- Channel:通道,信息流通;支持读取和写入数据,一个通道可以有多个Buffer;
- Buffer:缓存区,存放数据,支持读取和写入的切换;
二、使用步骤
1.服务器端
代码如下(示例):
package nio;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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.Set;/*** Create by zjg on 2022/9/11*/
public class NIOServer {public static void main(String[] args) {try {ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.bind(new InetSocketAddress(6666));Selector selector =Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while(true){if(selector.select(10000)==0){System.out.println("没有接收到监听事件");continue;}Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()){SelectionKey selectionKey = iterator.next();if(selectionKey.isAcceptable()){System.out.println("获取到新的连接");SocketChannel socketChannel = serverSocketChannel.accept();socketChannel.configureBlocking(false);socketChannel.register(selector,SelectionKey.OP_READ,ByteBuffer.allocate(1024));}if(selectionKey.isReadable()){SocketChannel socketChannel = (SocketChannel)selectionKey.channel();ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();int read = socketChannel.read(byteBuffer);if(read==-1){selectionKey.cancel();}else{String req=new String(byteBuffer.array()).trim();System.out.println("nio客户端说:"+req);String res= "服务器响应["+LocalDateTime.now().format(DateTimeFormatter.ISO_DATE)+" "+LocalDateTime.now().format(DateTimeFormatter.ISO_TIME)+"]:"+req;System.out.println(res);socketChannel.write(ByteBuffer.wrap(res.getBytes()));}}iterator.remove();}}} catch (IOException e) {e.printStackTrace();}}
}
2.客户端
代码如下(示例):
package nio;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;/*** Create by zjg on 2022/9/11*/
public class NIOClient {public static void main(String[] args) {try {SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666);if(!socketChannel.connect(inetSocketAddress)){while (!socketChannel.finishConnect()){System.out.println("等待连接完成!");}}String message="向往自由!";ByteBuffer byteBuffer = ByteBuffer.wrap(message.getBytes());socketChannel.write(byteBuffer);System.out.println("请求完成!");ByteBuffer allocate = ByteBuffer.allocate(1024);while (true){int read = socketChannel.read(allocate);if(read==0){continue;}System.out.println("---"+new String(allocate.array()).trim());socketChannel.close();break;}} catch (IOException e) {e.printStackTrace();}}
}
三、NIO零拷贝(推荐)
package nio;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;/*** Create by zjg on 2022/9/11*/
public class NIOZeroCopy {public static void main(String[] args) {FileChannel src = null;FileChannel dest = null;try {src=new FileInputStream("2.txt").getChannel();dest=new FileOutputStream("3.txt").getChannel();long start = System.currentTimeMillis();src.transferTo(0,src.size(),dest);long end = System.currentTimeMillis();System.out.println("copy完成,共"+src.size()+"byte,用时"+(end-start)+"毫秒");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {if(src!=null){try {src.close();} catch (IOException e) {e.printStackTrace();}}if(dest!=null){try {dest.close();} catch (IOException e) {e.printStackTrace();}}}}
}
四、NIO另一种copy
package nio;import java.io.File;
import java.io.IOException;
import java.nio.file.Files;/*** Create by zjg on 2022/9/18*/
public class NIOTest {public static void main(String[] args) {File source=new File("2.txt");File target=new File("4.txt");try {long start = System.currentTimeMillis();Files.copy(source.toPath(),target.toPath());long end = System.currentTimeMillis();System.out.println("copy完成,共"+source.length()+"byte,用时"+(end-start)+"毫秒");} catch (IOException e) {e.printStackTrace();}}
}
效率稍微慢点,用起来简单。
总结
回到顶部
刚开始写,请大佬指点。