设为首页 加入收藏

TOP

Java I/O(4):AIO和NIO中的Selector(二)
2023-07-25 21:25:59 】 浏览:62
Tags:Java I/O AIO NIO Selector
em.out.println(
new String(buffer.array())); // 关闭管道 sinkChannel.close(); sourceChannel.close(); } }

 

 

之前说过,同步指的按顺序一次完成一个任务,直到前一个任务完成并有了结果以后,才能再执行后面的任务。而异步指的是前一个任务结束后,并不等待任务结果,而是继续执行后一个任务,在所有任务都「执行」完后,通过任务的回调函数去获得结果。所以异步使得应用性能有了极大的提高。为了更加生动地说明什么是异步,可以来做个实验:

 

 

 

通过调用CompletableFuture.supplyAsync()方法可以很明显地观察到,处于位置2的「这一步先执行」会最先显示,然后才执行位置1的代码。而这就是异步的具体实现。

NIO为了支持异步,升级到了NIO2,也就是AIO。而AIO引入了新的异步Channel的概念,并提供了异步FileChannel和异步SocketChannel的实现。AIO的异步SocketChannel是真正的异步非阻塞I/O。通过代码可以更好地说明:

/**
 * AIO客户端
 *
 * @author xiangwang
 */
public class AioClient {
    public void start() throws IOException, InterruptedException {
        AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
        if (channel.isOpen()) {
            // socket接收缓冲区recbuf大小
            channel.setOption(StandardSocketOptions.SO_RCVBUF, 128 * 1024);
            // socket发送缓冲区recbuf大小
            channel.setOption(StandardSocketOptions.SO_SNDBUF, 128 * 1024);
            // 保持长连接状态
            channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
            // 连接到服务端
            channel.connect(new InetSocketAddress(8080), null,
                    new AioClientHandler(channel));
            // 阻塞主进程
            for(;;) {
                TimeUnit.SECONDS.sleep(1);
            }
        } else {
            throw new RuntimeException("Channel not opened!");
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        new AioClient().start();
    }
}

 

/**
 * AIO客户端CompletionHandler
 *
 * @author xiangwang
 */
public class AioClientHandler implements CompletionHandler<Void, AioClient> {
    private final AsynchronousSocketChannel channel;
    private final CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
    private final BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

    public AioClientHandler(AsynchronousSocketChannel channel) {
        this.channel = channel;
    }
    @Override
    public void failed(Throwable exc, AioClient attachment) {
        throw new RuntimeException("channel not opened!");
    }
    @Override
    public void completed(Void result, AioClient attachment) {
        System.out.println("send message to server: ");
        try {
            // 将输入内容写到buffer
            String line = input.readLine();
            channel.write(ByteBuffer.wrap(line.getBytes()));
            // 在操作系统中的Java本地方法native已经把数据写到了buffer中
            // 这里只需要一个缓冲区能接收就行了
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (channel.read(buffer).get() != -1) {
                buffer.flip();
                System.out.println("from server: " + decoder.decode(buffer).toString());
                if (buffer.hasRemaining()) {
                    buffer.compact();
                } else {
                    buffer.clear();
                }
                // 将输入内容写到buffer
                line = input.readLine();
                channel.write(ByteBuffer.wrap(line.getBytes()));
            }
        } catch (IOException | InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

 

/**
 * AIO服务端
 *
 * @author xiangwang
 */
public class AioServer {
    public void start() throws InterruptedException, IOException {
        AsynchronousServerSocketChannel channel = AsynchronousServerSocketChannel.open();
        if (channel.isOpen()) {
            // socket接受缓冲区recbuf大小
            channel.setOption(StandardSocketOptions.SO_RCVBUF, 4 * 1024);
            // 端口重用,防止进程意外终止,未释放端口,重启时失败
            // 因为直接杀进程,没有显式关闭套接字来释放端口,会等待一段时间后才可以重新use这个关口
            // 解决办法就是用SO_REUSEADDR
            channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
            channel.bind(new InetSocketAddress(
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇fastJson如何将json与对象、集合.. 下一篇为了讲明白继承和super、this关键..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目