2015-11-13 56 views
6

我正在研究不同語言的網絡IO API的體系結構,並詢問了如何在Java下實現Java中的異步IO API。 「舊」流IO API(1.4之前)提供同步阻塞讀/寫功能。 JDK 1.4 NIO API使用epoll/select來測試IO準備情況(通過SelectableChannel和Selector等向用戶公開)。這大概是Windows和* nix的情況。這是反應堆模式。現在,JDK7引入了NIO.2 API,其中提供了一個異步API(proactor模式),並使用內部(可配置)線程池在後臺執行IO,並在完成時回調用戶代碼。它大概在Windows上使用IOCP,但我想知道: 1.它在Linux上使用什麼,這是我感興趣的主要平臺。它使用epoll和朋友,還是使用線程池來阻止IO? 2. NIO.2中的實際IO(與平臺無關)由Java線程池中的用戶線程完成,還是由內核線程完成,並且Java線程池線程負責將字節緩衝區複製並回撥給用戶碼?JDK7 NIO.2在Linux上使用Epoll等?

回答

5

如果檢測到linux內核> = 2.6,則java.nio.channels.spi.SelectorProvider將使用epoll。

這裏是一塊DefaultSelectorProvider.javasource的(從Java 7):

public static SelectorProvider create() { 
    String osname = AccessController.doPrivileged(
     new GetPropertyAction("os.name")); 
    if ("SunOS".equals(osname)) { 
     return new sun.nio.ch.DevPollSelectorProvider(); 
    } 

    // use EPollSelectorProvider for Linux kernels >= 2.6 
    if ("Linux".equals(osname)) { 
     String osversion = AccessController.doPrivileged(
      new GetPropertyAction("os.version")); 
     String[] vers = osversion.split("\\.", 0); 
     if (vers.length >= 2) { 
      try { 
       int major = Integer.parseInt(vers[0]); 
       int minor = Integer.parseInt(vers[1]); 
       if (major > 2 || (major == 2 && minor >= 6)) { 
        return new sun.nio.ch.EPollSelectorProvider(); 
       } 
      } catch (NumberFormatException x) { 
       // format not recognized 
      } 
     } 
    } 

    return new sun.nio.ch.PollSelectorProvider(); 
} 

兩個NIO 2和「原始」一個(讓我們稱之爲NIO 1)必須使用低級別事件通知機制或Linux AIO API(這是相對較新的),因爲您永遠不知道應用程序運行的機器上的內核是什麼。我不會驚訝地發現NIO 2實際上使用Linux AIO或POSIX AIO(它們完全不同)。

+0

NIO.2是否使用SelectorProvider?我不太確定的是,NIO.2中的異步實現是否類似於NIO使用Epoll等進行準備檢查的方式。或者,它使用一組線程來模擬異步,從而阻止io? –

+0

「模擬異步」?在那裏沒有「模擬」 - 每個異步框架使用搶先(線程)或協作多任務(光纖,協程,綠色線程)來實現異步處理。 – DejanLekic

+0

據我瞭解,AsynchronousFileChannel不會阻塞對池的同步文件讀取,因此它不是真正的異步,而是模擬。另一方面,它確實選擇了真正異步的套接字:) –