Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 异步ByTechannel的线程含义_Java_Multithreading_Asynchronous_Nio_Completionhandler - Fatal编程技术网

Java 异步ByTechannel的线程含义

Java 异步ByTechannel的线程含义,java,multithreading,asynchronous,nio,completionhandler,Java,Multithreading,Asynchronous,Nio,Completionhandler,for的Javadoc表示操作是异步进行的,但是当到达流的末尾时会发生什么呢?是否允许实现在调用read()的同一线程内触发完成处理程序?从实现的角度来看,没有理由异步执行此操作,因为我们已经知道结果。类似地,如果用户试图读入ByteBuffer,其中remaining()返回0,则我们知道读取操作必须返回0 我这样问是因为我在自己的AsynchronousByteChannel实现中遇到了竞争条件。我正在调用一个完成处理程序,该处理程序在操作完成时对自身调用notify()。然后调用以下用户代

for的Javadoc表示操作是异步进行的,但是当到达流的末尾时会发生什么呢?是否允许实现在调用read()的同一线程内触发完成处理程序?从实现的角度来看,没有理由异步执行此操作,因为我们已经知道结果。类似地,如果用户试图读入ByteBuffer,其中remaining()返回0,则我们知道读取操作必须返回0

我这样问是因为我在自己的AsynchronousByteChannel实现中遇到了竞争条件。我正在调用一个完成处理程序,该处理程序在操作完成时对自身调用notify()。然后调用以下用户代码:

CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
  asyncByteChannel.read(handler);
  handler.wait();
}
CompletionHandler=。。。;
已同步(处理程序)
{
asyncByteChannel.read(处理程序);
handler.wait();
}
注意,用户假定在操作完成时会通知处理程序,但由于read()实际上是同步调用完成处理程序的,因此它会在wait()之前得到通知,后者将永远阻塞


规范是否要求我在单独的线程中更新CompletionHandler,或者用户是否应该知道调用read()的线程可能会同步执行某些操作?

即使在另一个线程上调用该处理程序,无法保证在
read
方法返回后,即在
wait()
启动后调用。(好的,同步锁似乎可以保证这一点。)

对于等待和锁定,应使用同步和布尔变量:

CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
   asyncByteChannel.read(handler);
   while(!handler.finished) {
     handler.wait();
   }
}
CompletionHandler=。。。;
已同步(处理程序)
{
asyncByteChannel.read(处理程序);
而(!handler.finished){
handler.wait();
}
}
。。。然后处理程序将
finished
变量设置为true。

查看它们总是在单独的线程中更新CompletionHandler,但Future在同一线程中更新。搜索变量hasSpaceToRead,以查找有问题的方法

我猜他们的推理路线是这样的:

  • 我们创建了返回给用户的未来,因此在我们返回对象之前,用户无法与它进行交互(同步等)
  • 用户创建CompletionHandler,因此我们无法控制实现的功能(据我们所知,我们可能会触发死锁!)。不要冒险,在单独的线程中启动完成处理程序
  • 更新:我被纠正了。根据“如果当前线程在通道组的线程池中,则直接调用处理程序,否则间接调用处理程序。”


    已解决:根据“如果I/O操作立即完成,并且启动线程是组中的池线程之一,那么启动线程可以直接调用完成处理程序。”

    如果允许我在主线程上处理CompletionHandler,您建议的解决方案将非常好。现在还不清楚是否是这样:)不,解决方案总是可用的。(如果不允许的话,这是没有必要的——但无论如何,你应该在一个循环中等待,因为可能会有虚假的唤醒。)我同意,但这不是这个问题的目的。问题在于规范是否允许在同一个线程上进行通知。它的线程模型很混乱。异步组上的javadoc不可解析。线程应该留给开发人员——这是最简单的部分。不幸的是,他们决定在这方面帮助我们。结果是非常复杂、不直观、缺乏记录(因为他们无法解释混乱)。一个不经意的评论员可能会发现API还不错——事实上,为什么它会很难呢?但当一个人认真地在上面构建一个应用程序时,其复杂性会让他发疯。