《Pro Java 7 NIO.2 》 The Asychronous Channel API 部分翻譯


Groups


the asynchronous API introduces a class named AsynchronousChannelGroup, which presents the concept of an asynchronous channel group, in which each asynchronous channel belongs to a channel group (the default one or a specified one) that shares a pool of Java threads.

These threads receive instructions to perform I/O events and they dispatch the results to the completion handlers.

The asynchronous channel group encapsulates thread pool and the resources shared by all the threads working for the channels. Also, the channel is in effect owned by the group, so if the group is closed, the channel is closed too.

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.


在異步AIP中AynchronousChannelGroup 表示 asynchronous chennel group 的概念。 每一個 asynchronous  channel 都屬於一個指定的group.
同時,group 共享java線程。這些線程接收異步i/o操作事件同時把結果分發到completion handler.
asynchronous  channel group操作線程池和被所有線程共享的自由。 channel 被擁有channel 的group影響,當group關閉時,channel也是關閉的。

Default Group
Besides the developer’s created groups, JVM maintains a system-widedefault groupthat is constructed automatically, useful for simple applications. 
When a group is not specified, or anullis passed instead, the asynchronous channels are bound, at construction time, to the default group. 

 public static AsynchronousServerSocketChannel open()throws IOException  
 This method returns an asynchronous server socket channel that is bound to the default group.

除了用戶自定義groups,java虛擬機本身保留系統默認的group,默認group被自動創建。 默認group可以用來創建簡單應用程序。
AsynchronousServerSocketChannel.open()方法調用時,默認group將自動創建,AsynchronousServerSocketChannel 實例將自動綁定到默認的group上面

Custom Groups
If the default group does not satisfy your needs, theAsynchronousChannelGroupclass provides three
methods for creating your own channel groups. For AsynchronousServerSocketChannel,
AsynchronousSocketChannel, andAsynchronousDatagramChannel(unavailable as of this writing), the
channel group is passed on creation in the open() method of each one.AsynchronousFileChanneldiffers
from the other channels in that, in order to use a custom thread pool, theopen()method takes an
ExecutorServiceinstead of anAsynchronousChannelGroup
Now, let’s see what the advantages and disadvantages of each supported thread pool are; these characteristics will help you to decide which one
is proper in your case.



當默認group不能滿足應用程序需要時,Asynchronouschannelgroup提供三種方式創建用戶自定義group.



Fixed Thread Pool
You can request a fixed thread pool by calling the following AsynchronousChannelGroup method:
public static AsynchronousChannelGroup withFixedThreadPool(int nThreads,ThreadFactory threadFactory) throws IOException
This method creates a channel group with a fixed thread pool. You must specify the factory to use when creating new threads and the number of threads.




The life cycle in a fixed thread pool follows a simple scenario:
a thread waits for an I/O event,completes I/O for the event, invokes a completion handler, and goes back to wait for more I/O events (the kerneldispatches events directly to these threads). 
When the completion handler terminates normally, the thread returns to the thread pool and waits for the next event.
 But if the completion handler does not complete in a timely manner, then it is possible to enter into an indefinitely blocking. 
If all threads “deadlock” inside a completion handler, then the application is blocked until a thread is available to execute again, and any new event will be queued until a thread is available. 
In the worst-case scenario, no thread can get free and the kernel can no longer execute anything. 
This issue may be avoided if you don’t use blocking or long operations inside a completion handler. 
Also, you may use a cached thread pool or timeouts for avoiding this issue.


第一種爲固定數量線程池。
主要: 固定數量線程池的生命週期遵循一個簡單的方案:
一個線程等待異步I/O 事件,完成I/O事件,調用competion handler方法,然後繼續等待更多的I/O事件。(注意:操作系統內核分發事件到這些線程中)。
當一個competion handler 正常結束時,線程將回到線程池中,繼續等待下一個I/O操作事件。
如果completion handler沒有在一定事件內完成,有可能進入阻塞狀態,如果所有的線程都死鎖,那麼應用程序進程將阻塞,直到存在線程可以繼續執行。
最糟糕的情況是,所有的線程都死鎖不再執行任何事情。
這個問題可以通過在competion handler中不使用任何鎖機制或者長時間的操作。
同時,可以使用緩衝線程池或者超時來避免這種問題。







Cached Thread Pool
You can request a cached thread pool by calling the followingAsynchronousChannelGroupmethod:
public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor,int initialSize) throws IOException
This method creates an asynchronous channel group with a given thread pool that creates new threads as needed.
You just need to specify the initial number of threads and an ExecutorService that creates new threads as needed.
It may reuse previously constructed threads when they are available.
In this case the asynchronous channel group will submit events to the thread pool that simply invoke completion handlers. 
But if the thread pool simply invokes the completion handlers, then who does the hard work and performs the I/O operations? The answer is the hidden thread pool.
This is a set of separate threads that waits for incoming I/O events.
More precisely, the kernel I/O operations are handled by one or more invisible internal threads that dispatch events to a cached pool, which in turn
invokes completion handlers.
The hidden thread pool is important because it greatly reduces the probability that the application
will be blocked (it solves the fixed thread pool issue) and guarantees that the kernel will be able to complete its I/O operations. 
But we still have an issue, because the cached thread pool needs unbounded queuing, which can make the queue grow infinitely and cause 
OutOfMemoryError—so monitor the queue (avoid locking all the threads and avoid feeding the queue forever). 
Avoiding the use of blocking or long operations inside completion handlers is still a good idea.

這樣可以重用已經存在的線程。這樣asynchronous  channel 可以提交異步io事件到線程池,線程池可以調用competion handler.
如果線程池執行調用completion handler ,到底誰來執行I/O操作呢??? 答案是:隱藏線程池。
隱藏線程池是另外一部分線程來處理連接I/O事件。
更準確的說,操作系統內核通過一個或者多個不可見內部線程執行IO操作同時分發事件到緩存線程池,緩存線程池回來調用completion handler.
隱藏線程池對於降低應用程序死鎖的概率非常重要和確保內核可以完成I/O 操作。
爲了避免死鎖活或者長時間在completion handler的操作 使用緩衝線程池是非常重要的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章