AsynchronousByteChannel.read()的Javadoc表示操作是异步进行的,但是当到达流末尾会发生什么?是否允许实现在调用read()的同一线程中触发完成处理程序?从实现的角度来看,没有理由异步执行此操作,因为我们已经知道了结果。类似地,如果用户尝试读入剩余()返回0的ByteBuffer,我们知道读操作必须返回0.
我问,因为我在自己的AsynchronousByteChannel实现中遇到了竞争状态。我正在调用一个完成处理程序,它在操作完成时调用notify()。然后我调用以下用户代码:
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
asyncByteChannel.read(handler);
handler.wait();
}
注意用户假设在操作完成时会通知处理程序,但是因为read()实际上同步调用了completion-handler,所以在wait()之前会通知它,而后者将永远阻塞。
规范是否要求我在单独的线程中更新CompletionHandler,或者用户是否应该知道调用read()的线程可以同步执行某些操作?
答案 0 :(得分:1)
即使在另一个线程上调用了处理程序,也无法保证在read
方法返回之后调用,即在wait()
启动之后。 (好的,同步锁似乎可以保证这一点。)
您应该使用同步和布尔变量进行等待和锁定:
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
asyncByteChannel.read(handler);
while(!handler.finished) {
handler.wait();
}
}
...然后你的处理程序会将finished
变量设置为true。
答案 1 :(得分:1)
查看http://www.docjar.com/html/api/sun/nio/ch/AsynchronousSocketChannelImpl.java.html它们总是在一个单独的线程中更新CompletionHandler,但Future在同一个线程中更新。搜索变量hasSpaceToRead
以查找相关方法。
我猜他们的推理方式是这样的:
更新:我有所纠正。根据{{3}}“如果当前线程在通道组的线程池中,则直接调用处理程序,否则间接调用它。”
已解决:根据Invoker.invoke()“I / O操作立即完成,并且启动线程是组中的池线程之一,则可以直接调用完成处理程序由发起主题。“