2015-10-07 48 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異常,做我想要的清理。