上一篇文章先容了 Java NIO 中 Buffer、Channel 和 Selector 的根基操纵,主要是一些接口操纵,较量简朴。
本文将先容非阻塞 IO 和异步 IO,也就是各人耳熟能详的 NIO 和 AIO。许多初学者大概分不清楚异步和非阻塞的区别,只是在各类场所能听到异步非阻塞这个词。
本文会先先容并演示阻塞模式,然后引入非阻塞模式来对阻塞模式举办优化,最后再先容 JDK7 引入的异步 IO,由于网上关于异步 IO 的先容相对较少,所以这部门内容我会先容得详细一些。
但愿看完本文,读者可以对非阻塞 IO 和异步 IO 的迷雾看得更清晰些,可能为初学者解开一丝丝迷惑也是好的。
NIO,JDK1.4,New IO,Non-Blocking IO
NIO.2,JDK7,More New IO,Asynchronous IO,严格地说 NIO.2 不只仅引入了 AIO
阻塞模式 IO
我们已经先容过利用 Java NIO 包构成一个简朴的客户端-处事端网络通讯所需要的 ServerSocketChannel、SocketChannel 和 Buffer,我们这里整合一下它们,给出一个完整的可运行的例子:
public class Server { public static void main(String[] args) throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 监听 8080 端口进来的 TCP 链接 serverSocketChannel.socket().bind(new InetSocketAddress(8080)); while (true) { // 这里会阻塞,直到有一个请求的毗连进来 SocketChannel socketChannel = serverSocketChannel.accept(); // 开启一个新的线程来处理惩罚这个请求,然后在 while 轮回中继承监听 8080 端口 SocketHandler handler = new SocketHandler(socketChannel); new Thread(handler).start(); } } }
这里看一下新的线程需要做什么,SocketHandler:
public class SocketHandler implements Runnable { private SocketChannel socketChannel; public SocketHandler(SocketChannel socketChannel) { this.socketChannel = socketChannel; } @Override public void run() { ByteBuffer buffer = ByteBuffer.allocate(1024); try { // 将请求数据读入 Buffer 中 int num; while ((num = socketChannel.read(buffer)) > 0) { // 读取 Buffer 内容之前先 flip 一下 buffer.flip(); // 提取 Buffer 中的数据 byte[] bytes = new byte[num]; buffer.get(bytes); String re = new String(bytes, "UTF-8"); System.out.println("收到请求:" + re); // 回应客户端 ByteBuffer writeBuffer = ByteBuffer.wrap(("我已经收到你的请求,你的请求内容是:" + re).getBytes()); socketChannel.write(writeBuffer); buffer.flip(); } } catch (IOException e) { IOUtils.closeQuietly(socketChannel); } } }
最后,贴一下客户端 SocketChannel 的利用,客户端较量简朴:
public class SocketChannelTest { public static void main(String[] args) throws IOException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("localhost", 8080)); // 发送请求 ByteBuffer buffer = ByteBuffer.wrap("1234567890".getBytes()); socketChannel.write(buffer); // 读取响应 ByteBuffer readBuffer = ByteBuffer.allocate(1024); int num; if ((num = socketChannel.read(readBuffer)) > 0) { readBuffer.flip(); byte[] re = new byte[num]; readBuffer.get(re); String result = new String(re, "UTF-8"); System.out.println("返回值: " + result); } } }
上面先容的阻塞模式的代码应该很好领略:来一个新的毗连,我们就新开一个线程来处理惩罚这个毗连,之后的操纵全部由谁人线程来完成。
那么,这个模式下的机能瓶颈在那边呢?
非阻塞 IO
说完了阻塞模式的利用及其缺点今后,我们这里就可以先容非阻塞 IO 了。