Java 在非阻塞文件描述符上选择

Java 在非阻塞文件描述符上选择,java,android,io,nio,Java,Android,Io,Nio,我有一个或多个非阻塞FileDescriptor对象(已经创建并从某个子系统传递给我)。我想等待,然后使用某种select()读取它们。如何在Java(Android)中实现这一点?我可以使用选择器类吗?看起来我们不能使用选择器s 那么,让我们尝试另一种方法 假设您有一个方法open(),该方法返回所需的FileDescriptor,但会阻塞某些IO操作。您希望能够在提取FileDescriptors时继续您的业务,而无需等待此操作,并且您希望知道它们何时准备就绪 试着这样做: // IMPOR

我有一个或多个非阻塞
FileDescriptor
对象(已经创建并从某个子系统传递给我)。我想等待,然后使用某种select()读取它们。如何在Java(Android)中实现这一点?我可以使用
选择器
类吗?

看起来我们不能使用
选择器
s

那么,让我们尝试另一种方法

假设您有一个方法
open()
,该方法返回所需的
FileDescriptor
,但会阻塞某些IO操作。您希望能够在提取
FileDescriptor
s时继续您的业务,而无需等待此操作,并且您希望知道它们何时准备就绪

试着这样做:

// IMPORTS
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class FileDescriptorFetcher extends Thread {
  final BlockingQueue<FileDescriptor> queue =
      new LinkedBlockingQueue<FileDescriptor>();
  // let's just pretend Openable provides FileDescriptors from open()
  final Openable[] from;
  boolean done;

  FileDescriptorFetcher(Openable[] fromThese) {
    from = fromThese;
    done = false;
    start();
  }

  @Override
  public void run() {
    for (Openable o : from)
      queue.offer(o.open());

    done = true;
  }

  public boolean isDone() {
    return done;
  }

  public boolean descriptorAvailable() {
    return !queue.isEmpty();
  }

  /* blocks if there are more descriptors to get and none are available,
   * returns null if all have been fetched already */
  public FileDescriptor fetchDescriptor() {
    return done
        ? null
        : queue.take();
  }
}
要尽快获取每个
文件描述符

while (!fetcher.isDone()) {
  doStuff(fetcher.fetchDescriptor());
}

阅读提供的另一个答案中的评论,我发现您正试图使VPN服务fd阻塞,这在较低的android版本中是不受支持的


我所做的是通过JNI代码使fd阻塞。希望这有帮助。

这就是问题所在。无法从FileDescriptor获取SelectableChannel。只需谷歌这个问题。。。我在问如何实现它克服这个问题那么,这里有一个哲学问题。为什么需要等待选择?他们到底在阻止什么?从我可以看出,您不想在实际的
FileDescriptor
上阻塞,它只引用已经完成的打开文件操作的实际结果。正如您所说,对于
java.nio
中的文件,似乎没有任何
SelectableChannel
s;您可能希望做的是创建一个新的
线程
对象,该对象打开文件流,并在作业完成时在内部列表的同步上下文中提供生成的
文件描述符
。我没有的文件描述符实际上不是文件系统FD。我是从VPN服务获得的(请参阅)。因此,需要用select()来阅读它。我用更一般地处理问题的方法来替换我的答案。这看起来怎么样?如果这仍然不是它,并且您希望从流中读取它们所指示的一些您根本没有描述过的过程,您最好的选择是为您获得的
FileDescriptor
对象实现一个
SelectableChannel
包装器,并将其与常规的
选择器一起使用。您是否找到了一个很好的解决方案?这里也有同样的问题(VpnService)。@CamHart启动API级别21,Android VpnService.Builder可以选择将fd设置为阻塞模式。看看这个
while (!fetcher.isDone()) {
  doStuff(fetcher.fetchDescriptor());
}