Блокировка потока Java в нативном методе, ожидающем завершения ввода-вывода - PullRequest
3 голосов
/ 01 ноября 2011

У меня есть блокировка Thread в нативном методе, который, в свою очередь, блокирует и ждет возврата функции linux read (include <fcntl.h>):

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

где g_fd является ли файловый дескриптор последовательного порта

В этой ситуации, как "прервать" поток блокировки?

РЕДАКТИРОВАТЬ для кого-то, кто имеет такой жепроблема:

1. Следует избегать бесконечной блокировки ввода-вывода.Нет очевидного способа прервать его

2. Ответ @Rohit Karlupia должен сработать

3. Хакерским способом является совместное использование файлового дескриптора между Java и собственным кодом,как показано в этой статье: http://www.kfu.com/~nsayer/Java/jni-filedesc.html Затем мы можем создавать прерываемые потоковые объекты Java IO с помощью FileDescriptor

Ответы [ 2 ]

0 голосов
/ 01 ноября 2011

Java поддерживает прерывистый ввод-вывод, но это будет работать только с классами ввода-вывода Java, а не с системными вызовами, непосредственно вызываемыми через собственный код. У Java есть пакеты для общения с последовательным портом. Посмотрите, можете ли вы использовать их вместо нативного кода.

Если нативный код неизбежен, вы можете сделать что-то подобное. - открыть ФД в неблокирующем режиме - для имитации поведения блокировки используйте select с одним fd, который вы создали выше - вместо использования бесконечного тайм-аута в select, используйте say per second timeout с циклом - чтобы прервать поток, вы можете установить флаг из другого потока, который может проверяться «кодом обертки» для чтения каждую секунду, когда он выходит из выбранного времени ожидания.

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;
             }
          }
       }
    }
}
0 голосов
/ 01 ноября 2011

Не уверен, что это сработает для вас, но в аналогичном случае (при чтении сокета ) я прибег к закрытию сокета как «прерывание». Вызов read () может затем вернуться. В моем случае он «вернулся», выдав исключение, которое я перехватил и обработал как прерывание. т.е.

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

Возможно, вам также придется проверить -1 (или какой-то другой специальный код).

...