- 30
- 0
问题描述
在写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();
} - 共 0 条
- 全部回答
-
萌新也要冲 普通会员 1楼
NIO(New IO)是一种面向多路复用的输入/输出流,它可以同时处理多个输入/输出请求,大大提高了系统的并发性。
在NIO中,每个线程都有自己的输入和输出流,所以每个线程都可以独立地处理读写请求。这种方式可以大大提高系统的并发性,因为多个线程可以同时处理多个读写请求,而不会互相影响。
以下是一个简单的例子,展示了如何在NIO中使用线程处理每一个读写请求:
```java import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel;
public class NioExample { public static void main(String[] args) throws IOException { FileChannel fileChannel = Channels.open("test.txt", 0644); ReadableByteChannel readableChannel = Channels.newChannel(fileChannel); WritableByteChannel writableChannel = Channels.newChannel(fileChannel);
// 线程1:读取 Thread thread1 = new Thread(() -> { try { readableChannel.readAllBytes(); System.out.println("Read from " + readableChannel); } catch (IOException e) { e.printStackTrace(); } }); // 线程2:写入 Thread thread2 = new Thread(() -> { try { writableChannel.writeAllBytes("Hello, World!"); System.out.println("Write to " + writableChannel); } catch (IOException e) { e.printStackTrace(); } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); }} ```
在这个例子中,我们创建了两个线程,一个线程负责读取文件,另一个线程负责写入文件。这两个线程可以在不阻塞主线程的情况下同时运行。
注意,这个例子使用了Java的NIOAPI,如果你的系统不支持NIO,你可能需要使用其他的并发编程库,如Java并发包(java.util.concurrent)或C++的std::thread。
- 扫一扫访问手机版
回答动态

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器更新之后。服务器里面有部分玩家要重新创建角色是怎么回事啊?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题函数计算不同地域的是不能用内网吧?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题ARMS可以创建多个应用嘛?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题在ARMS如何申请加入公测呀?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题前端小程序接入这个arms具体是如何接入监控的,这个init方法在哪里进行添加?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器刚到期,是不是就不能再导出存档了呢?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器的游戏版本不兼容 尝试更新怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器服务器升级以后 就链接不上了,怎么办?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器转移以后服务器进不去了,怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器修改参数后游戏进入不了,是什么情况?预计能赚取 0积分收益
- 回到顶部
- 回到顶部

