nio使用线程处理每一个读写请求的写法问题

问题描述

在写java nio的demo时,希望按照React的模式实现,对每一个已经就绪的请求,都在一个新的线程里处理。具体的代码如下面所示。

当一个客户端写完数据之后,断开连接时,会报错:

java.nio.channels.ClosedChannelException

显然这种写法是不合适或者不对的。看到网上用的是 attach() 方法

selectionKey.attach(new Acceptor(selector,selectionKey));

那么:
问题1: 我采用的写法,是哪里导致客户端关闭时报错,错误原因是什么?
问题2: attach()怎么用,为什么这种写法可以避免关闭客户端报错的情况?

相关代码

使用单独线程,进行select操作。

new Thread(() -> {
            try {
                while (selector.select() > 0) {
                    for (SelectionKey selectionKey : selector.selectedKeys()) {
                        try {
                            selector.selectedKeys().remove(selectionKey);
                            if (selectionKey.isAcceptable()) {
                                SocketChannel socketChannel = serverSocketChannel.accept();
                                socketChannel.configureBlocking(false);
                                socketChannel.register(selector, SelectionKey.OP_READ);
                            }
                            if (selectionKey.isReadable()) {
                                doRead(selectionKey);
                                
                            }
                        } catch (IOException e) {
                            selectionKey.cancel();
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

当遇到可读事件时,在一个新的线程里进行处理。

public void doRead(SelectionKey selectionKey) {
        new Thread(() -> {
            try {
                SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                String content = "";
                int c = 0;
                while ((c = socketChannel.read(byteBuffer)) > 0) {
                    byteBuffer.flip();
                    content += charset.decode(byteBuffer);
                }
                System.out.println(content);
                selectionKey.interestOps(SelectionKey.OP_READ);
                if (c == -1) {
                    selectionKey.cancel();
                    socketChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
ABOUTYOU
浏览 542回答 1
1回答
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java