在本机方法中等待I / O完成的Java线程阻塞

时间:2011-11-01 03:35:21

标签: java multithreading java-native-interface blocking interrupt

我在本机方法中有一个线程阻塞,这反过来阻塞并等待linux read函数(include <fcntl.h>)返回:

int n = read(g_fd, dest, len);

其中g_fd是串行端口的文件描述符

在这种情况下,如何“中断”阻塞线程?

对于遇到相同问题的人编辑

1.应避免使用无限阻塞IO。没有明显的方法可以打断它

2. @Rohit Karlupia的答案应该有效

3.一种hackish方式是在Java和本机代码之间共享文件描述符,如本文所示:http://www.kfu.com/~nsayer/Java/jni-filedesc.html然后我们可以使用FileDescriptor

创建可中断的Java IO流对象

2 个答案:

答案 0 :(得分:0)

不确定这是否适合您,但在类似的情况下(使用 socket 读取)我使用关闭套接字作为“中断”。然后read()调用可以返回。在我的情况下,它通过抛出一些我捕获并处理中断的异常来“返回”。即。

public int myRead(g_fd, dest, len) {
   try {
      return read(g_fd, dest, len);
   }
   catch (SomeIOExceptionIForgetWhatItWas ex) {
      throw new InterruptedException();
   }
}

您可能还需要检查-1(或其他一些特殊代码)。

答案 1 :(得分:0)

Java支持可中断的IO,但这只适用于java IO类,而不适用于通过本机代码直接调用的系统调用。 Java确实有用于与串口通信的软件包。看看你是否可以使用它们而不是本机代码。

如果本机代码不可避免,那么你可以做这样的事情。 - 以非阻塞模式打开fd - 要模拟阻止行为,请使用上面创建的单个fd选择 - 而不是在select中使用无限超时,使用循环中的每秒超时 - 要中断线程,你可以设置一个来自其他线程的标志,可以通过“包装器代码”进行检查,以便在选择超时时间内每秒读取一次。

int myread(int fd) {
    FDSET fdset = ...;
    while (at least one byte read or error) {
       add fd to fdset 
       select(fdset) 
       if (read events) {
          do real read 
          return;
       }else {
          if (timeout) {
             check global/object level interrupt flag 
             if (set interrupt flag) {
                return;
             }
          }
       }
    }
}