Notes on the Asynchronous I/O implementation
Fixed Thread Pool
An asynchronous channel group associated with a fixed thread pool of size N, submits N tasks that wait on I/O or completion events from the kernel. Each task simply dequeues an event, does any necessary I/O completion, and then dispatches directly to the user's completion handler that consumes the result. When the completion handler terminates normally then the task returns back to waiting on a next event. If the completion handler terminates due to an uncaught error or runtime exception then the task terminates and is immediately replaced by a new task. This is depicted in the following diagram:
理解:一个异步的管道组和一个固定大小(N)的线程池相关联,这个管道组提交N个任务。每个任务等待来自内核的I/O事件或者需要实现的事件。一个任务仅仅弹出一个事件并完成必要的I/O操作,然后将结果直接派发给相应的用户回调函数。当回调函数正常结束的时候,任务会返回并等待下一个事件。如果在运行时意外终止的话,任务会直接终止并立即被一个新的任务所替代。
This configuration is relatively simple and delivers good performance for suitably designed applications. Note that it does not support the creation of threads on-demand or trimming back of the thread pool when idle. It is also not suitable for applications with completion handler implementations that block indefinitely; if all threads are blocked in completion handlers then I/O events cannot be serviced (forcing the operating system to queue accepted connections for example). Tuning requires choosing an appropriate value for N.
理解:这种配置相对简单而且在适合的应用场景中有较好的表现。注意这种设计不支持根据需求来创建合适大小的线程池或者当线程池闲置较多线程的时候对其进行消减。当回调函数会不确定阻塞的时候也不适合用这种模型。如果所有的线程都阻塞在回调函数的时候,I/O事件就无法被服务(操作系统会强制弹出已接受的链接)
User-supplied Thread Pool
An asynchronous channel group associated with a user-supplied thread pool submits tasks to the thread pool that simply invoke the user's completion handler. I/O and completion events from the kernel are handled by one or more internal threads that are not visible to the user application. This configuration is depicted in the following diagram:
理解:一个一步管道组和一个用户提供的线程池相关联,这个线程池用来提交任务给仅仅执行用户回调函数的线程池。内核I/O或者执行事件被一或多个用户程序不可见的内部线程来执行。
This configuration works with most thread pools (cached or fixed) with the following exceptions:
- The thread pool must support unbounded queueing.
- The thread that invokes the execute method must never execute the task directly. That is, internal threads do not invoke completion handlers.
- Thread poool keep alive must be disabled on older editions of Windows. This restriction arises because I/O operations are tied to the initiating thread by the kernel.
This configuration delivers good performance despite the hand-off per I/O operation. When combined with a thread pool that creates threads on demand, it is suitable for use with applications that have completion handlers that occasionally need to block for long periods (or indefinitely). The value of M, the number of internal threads, is not exposed in the API and requires a system property to configure (default is 1).
理解: 这种模型需要三个要求:(1)线程池必须支持无限的队列(2)用于调用执行方法的线程不能够直接执行任务。也就是内部线程不能调用用户回调函数(3)线程池在老的window版本上无法一直存活。导致这个限制的原因是I/O操作和内核的初始化线程相关联 尽管线程间的I/O传递操作会有一定的性能开销,但这种模式仍然有较好的表现。当一个应用中有导致长时间阻塞或者不定期阻塞的回调函数的时候,就非常适合通过线程池来根据需求创建线程。内部线程的数量需要系统属性来配置,并没有给用户提供API接口.(也就是说当用户线程中的某些I/O操作会导致长时间或不定期阻塞的时候,用户线程将这些I/O操作传递给线程池中的某个线程来执行,而自己直接执行接下来的操作,尽管线程间的上下文传递会有一定的性能开销,但在某些应用场合下会有较好的表现)
Default Thread Pool
Simpler applications that do not create their own asynchronous channel group will use the default group that has an associated thread pool that is created automatically. This thread pool is a hybrid of the above configurations. It is a cached thread pool that creates threads on demand (as it is may be shared by different applications or libraries that use completion handlers that invoke blocking operations).
As with the fixed thread pool configuration it has N threads that dequeue events and dispatch directly to the user's completion handler. The value of N defaults to the number of hardware threads but may be configured by a system property. In addition to N threads, there is one additional internal thread that dequeues events and submits tasks to the thread pool to invoke completion handlers. This internal thread ensures that the system doesn't stall when all of the fixed threads are blocked, or otherwise busy, executing completion handlers.
理解:简单的应用程序可能不会创建自己的异步管道组,而是直接用默认自动创建的管道组。这个管道组有一个混合模式的线程池(上面两种模式)和他关联。该线程池是一个根据需求来创建线程的缓存线程池,它会被多个包含阻塞操作的应用程序或库所共享。根据固定线程池配置文件,线程池有N个线程来从队列中弹出事件并直接分发给用户回调函数.根据系统配置文件设置的属性,N默认和硬件的线程数相等。
除了N个固定线程外,还有一个内部线程用来弹出事件并提交相应的任务给线程池来调用用户回调函数。
内部线程保证当所有固定线程阻塞,忙碌或者执行回调函数的时候时候系统不会停滞。
What happens when an I/O operation completes immediately?
When an I/O operation completes immediately then the API allows for the completion handler to be invoked directly by the initiating thread if the initiating thread itself is one of the pooled threads. This creates the possibility that there may be several completion handlers on a thread's stack. The following diagram depicts a thread stack where a read or write method has completed immediately and the completion handler invoked directly. The completion handler, in turn, initiates another I/O operation that completes immediately and so its completion handler is invoked directly, and so on.
理解:当一个I/O操作完成的时候,API允许回调函数被线程池中的某个正在初始化的线程调用。这样一个线程的栈中可能就有多个回调函数(红色的completion handler frame)。下图描述了一个线程栈中的读写方法完成时,回调函数被直接调用。这个回调函数又会实例化另一个I/O操作,当操作完成时,其所对应的回调函数立刻被执行,轮流依次下去。

By default, the implementation allows up to 16 I/O operations to complete directly on the initiating thread before requiring that all completion handlers on the thread stack terminate. This policy helps to avoid stack overflow and also starvation that could arise if a thread initiates many I/O operations that complete immediately. This policy, and the maximum number of completion handler frames allowed on a thread stack is configured by a system property where required. An addition to the API, in the future, may allow an application to specify how I/O operations that complete immediately be handled.
理解:默认情况下,这个方案允许16个I/O操作在初始化线程栈上的所有回调终止前直接完成。这样有助于避免栈溢出和栈饥饿,当一个线程发起太多可以直接完成的I/O操作的时候。线程栈上最多能有多少个回调函数帧是由系统属性配置的。今后API可能允许程序去指定当I/O操作完成时回调函数如何被立刻执行。
Direct Buffers
The asynchronous I/O implementation is optimized for use with direct buffers. As with SocketChannels, all I/O operations are done using direct buffers. If an application initiates an I/O operation with a non-direct buffer then the buffer is transparently substituted with a direct buffer by the implementation.
By default, the maximum memory that may be allocated to direct buffers is equal to the maximum java heap size (Runtime.maxMemory). This may be configured, where required, using the MaxDirectMemorySize VM option (eg: -XX:MaxDirectMemorySize=128m).
The MBean browser in jconsole can be used to monitor the resources associated with direct buffers.
理解:为了使用直接内存缓冲区,异步I/O已经做了优化。正如套接字管道一样,所有的I/O操作都通过直接内存来完成。如果一个应用通过非直接内存缓冲区完成了一个I/O操作,那么这个内存缓冲区接下来会透明地被直接内存缓冲区所替代。默认情况下,所能分配的最大直接内存和java的最大堆内存大小相等。如果需要的话可以通过设置配置文件中的选项来改变大小。

public abstract class AsynchronousChannelGroup
extends Object
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. In addition to handling I/O events, the pooled threads may also execute other tasks required to support the execution of asynchronous I/O operations.
An asynchronous channel group is created by invoking the withFixedThreadPool or withCachedThreadPoolmethods defined here. Channels are bound to a group by specifying the group when constructing the channel. The associated thread pool is owned by the group; termination of the group results in the shutdown of the associated thread pool.
In addition to groups created explicitly, the Java virtual machine maintains a system-wide default group that is constructed automatically. Asynchronous channels that do not specify a group at construction time are bound to the default group. The default group has an associated thread pool that creates new threads as needed. The default group may be configured by means of system properties defined in the table below. Where theThreadFactory for the default group is not configured then the pooled threads of the default group are daemonthreads.
理解:异步管道组是为了资源共享,它封装了完成组内所有管道发起的I/O操作的机制并且有一个与之关联的线程池,这个线程池接处理提交的I/O事件并将结果分发给相应的回调函数。除了处理I/O事件,线程池也可用来执行其他需要异步操作的的任务。一个异步管道通过调用withFixedThreadPool或者withCachedThreadPoolmethods来创建。管道在创建的时候都绑定到了一个组里面。线程池被相应的管道组所有,如果管道终止的话相应的线程池也会死掉。除了用户创建的管道组,java虚拟机也保持一个自动创建的管道组,在创建时没有声明所属管道组的管道将自动绑定到虚拟机的管道组,虚拟机的管道组有一个关联的线程池用来创建需要的线程。默认的管道组可以通过系统配置文件进行配置。如果默认管道组的ThreadFactory属性没有配置的话,那么和管道组关联的线程就是守护线程.
| System property | Description |
|---|---|
java.nio.channels.DefaultThreadPool.threadFactory |
The value of this property is taken to be the fully-qualified name of a concrete |
java.nio.channels.DefaultThreadPool.initialSize |
The value of the 理解: |


浙公网安备 33010602011771号