2015-10-07 44 views
0

可以指定java I/O操作的任何超时类型吗?带有超时的Java I/O

我们有一个情况,我们的NFS文件系统冻结,然后调用FileOutputStream.write()也冻结。随着超时,我们可能会检测到这种情况并采取一些行动。

===============

一个解决方案,来我的心是运行某种对线程池检查,并等待与超时的结果。但我不知道将与此调用发生什么,它可能会挂起,不释放文件描述符等。

taskExecutor.submit(new FilesystemCheck(filepath)).get(timeout, TimeUnit.SECONDS); 

与赎回

public static class FilesystemCheck implements Callable<Boolean> { 

     private final String path; 

     public FilesystemCheck(String path) { 
      this.path = path; 
     } 

     @Override 
     public Boolean call() throws Exception { 

      return Files.exists(Paths.get(path)); 

     } 
    } 
+0

可能重复的[是否有可能从一个InputStream超时读取?](http://stackoverflow.com/questions/804951/is-it-possible-to-read-from-a-inputstream-with -a超时) –

+0

NFS timemouts是一个可以追溯到30年的问题。这是我非常认为的观点,即应用程序不应该以任何方式使用共享文件系统。 – EJP

回答

0

假设您的流不是由支持套接字(所以你不能使用Socket.setSoTimeout()),我认为解决这类问题的标准方法是使用Future。

假设我有以下的执行和流:

ExecutorService executor = Executors.newFixedThreadPool(2); 
    final PipedOutputStream outputStream = new PipedOutputStream(); 
    final PipedInputStream inputStream = new PipedInputStream(outputStream); 

我有笔者,然后写入一些数据写入最后一块数据,并关闭流之前等待5秒:

Runnable writeTask = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       outputStream.write(1); 
       outputStream.write(2); 
       Thread.sleep(5000); 
       outputStream.write(3); 
       outputStream.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
    executor.submit(writeTask); 

阅读本文的正常方法如下。读出将无限期地阻止对数据等这样就完成了5秒:

long start = currentTimeMillis(); 
    int readByte = 1; 
    // Read data without timeout 
    while (readByte >= 0) { 
     readByte = inputStream.read(); 
     if (readByte >= 0) 
      System.out.println("Read: " + readByte); 
    } 
    System.out.println("Complete in " + (currentTimeMillis() - start) + "ms"); 

输出:

读:1

阅读:2

阅读:3

在5001ms完成

如果还有一个更基本的问题,比如作者没有回应,读者会永远屏蔽。如果我包裹读取在以后的,我可以然后控制超时如下:

int readByte = 1; 
    // Read data with timeout 
    Callable<Integer> readTask = new Callable<Integer>() { 
     @Override 
     public Integer call() throws Exception { 
      return inputStream.read(); 
     } 
    }; 
    while (readByte >= 0) { 
     Future<Integer> future = executor.submit(readTask); 
     readByte = future.get(1000, TimeUnit.MILLISECONDS); 
     if (readByte >= 0) 
      System.out.println("Read: " + readByte); 
    } 

输出:

读:1

阅读:2

在线程异常(FutureTask.java:91)“main”java.util.concurrent.TimeoutException at java.util.concurrent.FutureTask $ Sync.innerGet(FutureTask.java:228) at java.util.concurrent.FutureTask.get(FutureTask.java:91) 在test.InputStreamWithTimeoutTest.main(InputStreamWithTimeoutTest.java:74)

我能赶上TimeoutException异常,做我想要的清理。