java7 AIO / NIO 2 小记
来源:互联网 发布:mac显示桌面快捷键 编辑:程序博客网 时间:2024/06/04 07:11
概述
JDK7 已经大致确定发布时间。JSR 203 提出很久了。2009.11.13,JDK7 M5(b76)已经发布。JSR 203 习惯上称为 NIO.2,主要包括新的:
- 异步 I/O(简称 AIO);
- Multicase 多播;
- Stream Control Transport Protocol(SCTP);
- 文件系统 API;
- 以及一些 I/O API 的更新,例如:java.io.File.toPath,NetworkChannel 的完整抽象,等等。
BIO -> NIO -> AIO,Jva IO 性能逐步突飞猛进,谁还在说IO是Java的硬伤!
BIO几乎已经是老掉牙的东西,最简单,性能很差,不详说了;
NIO让人惊讶的IO性能飞跃,由于java5就开始有了,网上教程也满大街,著名的实用框架有 Netty 和 Mina,不多说了;
AIO,异步IO,这个就不是很为人所很熟知了,java7以后引入的异步IO,引入不少的新操作,小记下:
文件系统 API
File类其实名字有点儿误导人,它并不是指真正的文件,它的本质是用一种依赖系统的路径名来描述文件或者目录。这个通俗点儿讲不就是path么
public static void main(String[] args) { //PS: task 是桌面上的一个文本文件 //获得path方法一,e:/logs/access.log Path path = FileSystems.getDefault().getPath("/home/conquer/Desktop", "task"); System.out.println(path.getNameCount()); //获得path方法二,用File的toPath()方法获得Path对象 File file = new File("/home/conquer/Desktop/task"); Path pathOther = file.toPath();// File 到 Paht的转换 //0,说明这两个path是相等的 System.out.println(path.compareTo(pathOther)); //获得path方法三 Path path3 = Paths.get("/home/conquer/Desktop", "task"); System.out.println(path3.toString()); //join two paths Path path4 = Paths.get("/home/conquer/Desktop"); System.out.println("path4: " + path4.resolve("task")); System.out.println("--------------分割线---------------"); try { if(Files.isReadable(path)){ //注意此处的newBufferedRead的charset参数,如果和所要读取的文件的编码不一致,则会抛出异常 //java的新特性,不用自己关闭流 BufferedReader br = Files.newBufferedReader(path, Charset.defaultCharset());//new BufferedReader(new FileReader(new File("e:/logs/access.log")));// String line = ""; while((line = br.readLine()) != null){ System.out.println(line); } br.close(); }else{ System.err.println("cannot readable"); } } catch (IOException e) { System.err.println("error charset"); } } public static void main0(String[] args) { /** nio2 */ Path file = Paths.get("/home/conquer/Desktop/task"); System.out.println("file name:" + file.getFileName()); System.out.println("name count:" + file.getNameCount()); System.out.println("parent:" + file.getParent() + " root:" + file.getRoot()); File file1=file.toFile(); System.out.println(file1.exists()); //其他定义方式 /**Define an Absolute Path*/// Path path = Paths.get("C:/rafaelnadal/tournaments/2009/BNP.txt");// Path path = Paths.get("C:/rafaelnadal/tournaments/2009", "BNP.txt");// Path path = Paths.get("C:", "rafaelnadal/tournaments/2009", "BNP.txt");// Path path = Paths.get("C:", "rafaelnadal", "tournaments", "2009", "BNP.txt");// /**Define a Path Relative to the File Store Root*/// Path path = Paths.get("/rafaelnadal/tournaments/2009/BNP.txt");// Path path = Paths.get("/rafaelnadal","tournaments/2009/BNP.txt");// /**Define a Path Relative to the Working Folder*/// Path path = Paths.get("rafaelnadal/tournaments/2009/BNP.txt");// Path path = Paths.get("rafaelnadal","tournaments/2009/BNP.txt"); }
异步 I/O(简称 AIO)
- AIO 的核心概念:发起非阻塞方式的 I/O 操作。当 I/O 操作完成时通知。
- 应用程序的责任就是:什么时候发起操作? I/O 操作完成时通知谁?
AIO 的 I/O 操作,有两种方式的 API 可以进行:Future 方式 和 Callback 方式。
Future 方式:即提交一个 I/O 操作请求(accept/read/write),返回一个 Future。然后您可以对 Future 进行检查(调用get(timeout)),确定它是否完成,或者阻塞 IO 操作直到操作正常完成或者超时异常。使用 Future 方式很简单,需要注意的是,因为Future.get()
是同步的,所以如果不仔细考虑使用场合,使用 Future 方式可能很容易进入完全同步的编程模式,从而使得异步操作成为一个摆设。如果这样,那么原来旧版本的 Socket API 便可以完全胜任,大可不必使用异步 I/O.
Callback 方式:即提交一个 I/O 操作请求,并且指定一个 CompletionHandler
。当异步 I/O 操作完成时,便发送一个通知,此时这个 CompletionHandler 对象的 completed 或者 failed 方法将会被调用。
JAVA AIO 示例代码:
服务端:
package aio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousServerSocketChannel;import java.nio.channels.AsynchronousSocketChannel;import java.nio.channels.CompletionHandler;import java.nio.charset.Charset;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;import java.util.concurrent.TimeoutException;public class AIOServer { public final static int PORT = 9888; private AsynchronousServerSocketChannel server; public AIOServer() throws IOException { server = AsynchronousServerSocketChannel.open().bind( new InetSocketAddress(PORT)); } public void startWithFuture() throws InterruptedException, ExecutionException, TimeoutException { while (true) {// 循环接收客户端请求 Future<AsynchronousSocketChannel> future = server.accept(); AsynchronousSocketChannel socket = future.get();// get() 是为了确保 accept 到一个连接 handleWithFuture(socket); } } public void handleWithFuture(AsynchronousSocketChannel channel) throws InterruptedException, ExecutionException, TimeoutException { ByteBuffer readBuf = ByteBuffer.allocate(2); readBuf.clear(); while (true) {// 一次可能读不完 //get 是为了确保 read 完成,超时时间可以有效避免DOS攻击,如果客户端一直不发送数据,则进行超时处理 Integer integer = channel.read(readBuf).get(10, TimeUnit.SECONDS); System.out.println("read: " + integer); if (integer == -1) { break; } readBuf.flip(); System.out.println("received: " + Charset.forName("UTF-8").decode(readBuf)); readBuf.clear(); } } public void startWithCompletionHandler() throws InterruptedException, ExecutionException, TimeoutException { server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() { public void completed(AsynchronousSocketChannel result, Object attachment) { server.accept(null, this);// 再此接收客户端连接 handleWithCompletionHandler(result); } @Override public void failed(Throwable exc, Object attachment) { exc.printStackTrace(); } }); } public void handleWithCompletionHandler(final AsynchronousSocketChannel channel) { try { final ByteBuffer buffer = ByteBuffer.allocate(4); final long timeout = 10L; channel.read(buffer, timeout, TimeUnit.SECONDS, null, new CompletionHandler<Integer, Object>() { @Override public void completed(Integer result, Object attachment) { System.out.println("read:" + result); if (result == -1) { try { channel.close(); } catch (IOException e) { e.printStackTrace(); } return; } buffer.flip(); System.out.println("received message:" + Charset.forName("UTF-8").decode(buffer)); buffer.clear(); channel.read(buffer, timeout, TimeUnit.SECONDS, null, this); } @Override public void failed(Throwable exc, Object attachment) { exc.printStackTrace(); } }); } catch (Exception e) { e.printStackTrace(); } } public static void main(String args[]) throws Exception {// new AIOServer().startWithFuture(); new AIOServer().startWithCompletionHandler(); Thread.sleep(100000); }}
客户端:
package aio;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousSocketChannel;public class AIOClient { public static void main(String... args) throws Exception { AsynchronousSocketChannel client = AsynchronousSocketChannel.open(); client.connect(new InetSocketAddress("localhost", 9888)).get(); client.write(ByteBuffer.wrap("123456789".getBytes())); Thread.sleep(1111111); }}
AIO模型,简单,高效,以后的IO通信就用它了!!!
- java7 AIO / NIO 2 小记
- BIO--NIO-AIO(IOCP在Java7中的实现)
- Java BIO、NIO、AIO(NIO.2) 区别
- NIO AIO
- java7 AIO初体验
- java7输入输出流中NIO.2
- java7 nio 例子
- Java_BIO/NIO/AIO
- Java_BIO/NIO/AIO
- BIO/AIO/NIO
- Java_BIO/NIO/AIO
- BIO AIO NIO
- Java IO NIO AIO
- BIO,NIO,AIO
- Java_BIO/NIO/AIO
- BIO、NIO、AIO区别
- java BIO NIO AIO
- Java_BIO/NIO/AIO
- C++/MFC修行之路(4)Tab Control的使用
- SecureCRT配置
- CentOS之—— CentOS7源码安装cmake
- 2440内存初始化
- 设置控件透明度
- java7 AIO / NIO 2 小记
- Log4j 入门总结
- 使用scp命令进行文件上传到服务器
- java 集合知识点(未完)
- 设置边框圆角
- undefined reference to 问题总结(转载)
- Android内存泄漏总结
- 改变状态栏的颜色使其与APP风格一体化
- Android四大组件之Service的使用