Java AIO 認識

在基本熟悉了JDK7中異步IO的關鍵類,以後有助於我們深入學習。在java語言和平臺中,存在廣泛使用的網絡開源庫屈指可數。netty 和mina出自韓國人之手,netty和mina主要使用select網絡模型,主要使用jdk中的nio類庫。netty 和mina在各個行業被廣泛使用。 netty 和mina 以及 java nio本身都是對reactor 模式的實現。在操作系統層面都是通過select函數來實現。在windows操作系統中,出現I/o Completion port 後,被廣泛使用來提供網絡效率。我們RPG遊戲服務器本身就是通過I/O Completion Port實現的。

2009年 jdk7出現後,在語言本身對異步IO操作進行了封裝,形成了NIO.2 即AIO. AIO框架 僅僅有一個griizly 以及grizzly自身的升級版。grizzly 的開發者是sun公司研發AIO的主要領導者。更有意思的是,grizzly作者目前從事遊戲架構設計,同時也是一名創業者。以後的篇章中,我們主要以grizzly爲學習案例。雖然grizzly使用範圍,文檔都不如netty 和mina,但是grizzly 對於AIO的簡單封裝足夠我們學習使用。在Windows平臺下面,Java AIO是通過IOCP實現的,這個可以通過OpenJDK源代碼證實。


對於JDK7中關於socket 異步IO操作關鍵類源代碼剖析:


public interface AsynchronousChannel  extends Channel
{
    void close() throws IOException;
}

  • A channel that supports asynchronous I/O operations. Asynchronous I/O operations will usually take one of two forms: 
  • A channel that implements this interface is asynchronously closeable: If an I/O operation is outstanding on the channel and the channel'sclose method is invoked, then the I/O operation fails with the exceptionAsynchronousCloseException.Asynchronous channels are safe for use by multiple concurrent threads.
  •  Some channel implementations may support concurrent reading and writing, but may not allow more than one read and one write operation to be outstanding at any given time. 
在JDK7開始存在異步IO操作。AsynchronousChannel接口支持異步IO操作。異步IO操作經常使用如下兩種形式。

AsynchronousChannel   接口中存在異步close()方法。當一個IO操作是未完成的,當調用close()方法,則IO操作會拋出異常。

一些AsynchronousChannel   的實現支持併發讀寫,但是不允許在同時多個線程同時讀寫一個未完成的IO操作。


public interface AsynchronousByteChannel extends AsynchronousChannel
{
    <A> void read(ByteBuffer dst, A attachment,CompletionHandler<Integer,? super A> handler);
    <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer,? super A> handler);
    Future<Integer> read(ByteBuffer dst);
    Future<Integer> write(ByteBuffer src);
}

  • An asynchronous channel that can read and write bytes
  • that ByteBuffers are not safe for use by multiple concurrent threads. 
    When a read or write operation is initiated then care must be taken to ensure that the buffer is not accessed until the operation completes.
一個支持對字節序進行讀寫的異步Channel。

ByteBuffers 在多個併發線程下使用是不安全的。一個異步IO讀寫操作必須確保在IO操作完成後,ByteBuffers 才能被訪問。

在AsynchronousByteChannel  接口中支持2種方式來進行對字節的讀寫操作。




public abstract class AsynchronousServerSocketChannel implements AsynchronousChannel, NetworkChannel
{
    private final AsynchronousChannelProvider provider;


    /**
     * Initializes a new instance of this class.
     */
    protected AsynchronousServerSocketChannel(AsynchronousChannelProvider provider) 
{
        this.provider = provider;
    }
    /**
     * Returns the provider that created this channel.
     */
    public final AsynchronousChannelProvider provider() 
{
        return provider;
    }
    public static AsynchronousServerSocketChannel open(AsynchronousChannelGroup group) throws IOException
    {
        AsynchronousChannelProvider provider = (group == null) ? AsynchronousChannelProvider.provider() : group.provider();
        return provider.openAsynchronousServerSocketChannel(group);
    }
    public static AsynchronousServerSocketChannel open()throws IOException
    {
        return open(null);
    }
    public final AsynchronousServerSocketChannel bind(SocketAddress local) throws IOException
    {
        return bind(local, 0);
    }
    public abstract AsynchronousServerSocketChannel bind(SocketAddress local, int backlog)throws IOException;


    public abstract <T> AsynchronousServerSocketChannel setOption(SocketOption<T> name, T value) throws IOException;


    public abstract <A> void accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler);
    public abstract Future<AsynchronousSocketChannel> accept();
}

An asynchronous channel for stream-oriented listening sockets. 
An asynchronous server-socket channel is created by invoking the open method of this class.
A newly-created asynchronous server-socket channel is open but not yet bound.
It can be bound to a local address and configured to listen for connections by invoking the bind method. 
the accept method is used to initiate the accepting of connections to the channel's socket.
Channels of this type are safe for use by multiple concurrent threads though at most one accept operation can be outstanding at any time.
If a thread initiates an accept operation before a previous accept operation has completed then an AcceptPendingException will be thrown. 


AsynchronousServerSocketChannel  是一個支持面向流的服務器端監聽socket.
可以通過靜態open()方法來創建一個server-socket.一個新創建的server-socket是打開的,但是沒有綁定指定端口。
可以通過bind()函數來綁定指定端口。在AsynchronousServerSocketChannel 類中存在2種方式來接受新socket的鏈接到臨。
雖然,在同一時刻只能最多有一個線程來調用accept()方法,但是在多個線程併發使用AsynchronousServerSocketChannel 是安全的。
如果在一個線程調用accept()操作完成前,另外一個線程來執行accept操作,將會拋出AcceptPendingException異常。
在accept()兩種形式,在以後會詳細介紹。在AsynchronousServerSocketChannel   類中通過指定open()參數來創建實例非常重要。

public abstract class AsynchronousChannelGroup 
{
    private final AsynchronousChannelProvider provider;
    protected AsynchronousChannelGroup(AsynchronousChannelProvider provider) 
{
        this.provider = provider;
    }
    public final AsynchronousChannelProvider provider()
{
        return provider;
    }
    public static AsynchronousChannelGroup withFixedThreadPool(int nThreads,ThreadFactory threadFactory) throws IOException
    {
        return AsynchronousChannelProvider.provider().openAsynchronousChannelGroup(nThreads, threadFactory);
    }


    public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor,int initialSize)throws IOException
    {
        return AsynchronousChannelProvider.provider() .openAsynchronousChannelGroup(executor, initialSize);
    }
    public static AsynchronousChannelGroup withThreadPool(ExecutorService executor)throws IOException
    {
        return AsynchronousChannelProvider.provider().openAsynchronousChannelGroup(executor, 0);
    }
    public abstract boolean isShutdown();
    public abstract boolean isTerminated();
    public abstract void shutdown();
    public abstract void shutdownNow() throws IOException;
    public abstract boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
}



An asynchronous channel group encapsulates the mechanics required to handle the completion of I/O operations initiated by asynchronous channels that are bound to the group. 
A group has an associated thread pool to which tasks are submitted to handle I/O events and dispatch to completion-handlers that consume the result of asynchronous operations performed on channels in the group.
An asynchronous channel group is created by invoking the withFixedThreadPool or withCachedThreadPool methods defined here.
The associated thread pool is owned by the group; termination of the group results in the shutdown of the associated thread pool. 


Threading
The completion handler for an I/O operation initiated on a channel bound to a group is guaranteed to be invoked by one of the pooled threads in the group.
This ensures that the completion handler is run by a thread with the expected identity. 
Where an I/O operation completes immediately, and the initiating thread is one of the pooled threads in the group then the completion handler may be invoked directly by the initiating thread. 
To avoid stack overflow, an implementation may impose a limit as to the number of activations on the thread stack. 
 Some I/O operations may prohibit invoking the completion handler directly by the initiating thread 。


在JDK7中對於異步IO操作主要有2中方式。這兩種方式將會重點講解。其中一個方式存在一個接口。

public interface CompletionHandler<V,A> 
{


    void completed(V result, A attachment);
    void failed(Throwable exc, A attachment);
}




A handler for consuming the result of an asynchronous I/O operation. 
The asynchronous channels defined in this package allow a completion handler to be specified to consume the result of an asynchronous operation.
The completed method is invoked when the I/O operation completes successfully.
The failed method is invoked if the I/O operations fails. 
The implementations of these methods should complete in a timely manner so as to avoid keeping the invoking thread from dispatching to other completion handlers.


爲了處理異步IO結果的處理器。當異步IO操作完成時,completed()函數將被調用。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章