NIO2中异步通道、线程池知识点

来源:互联网 发布:手机表格制作软件 编辑:程序博客网 时间:2024/06/06 20:32

概述:异步通道 API 提供两种对已启动异步操作的监测与控制机制:
一:
第一种是通过返回一个 java.util.concurrent.Future 对象来实现,它将会建模一个挂起操作,并可用于查询其状态以及获取结果。
第一个返回java.util.concurrent.Future,代表等待结果,你可以使用Future特性等待I/O操作结束;

二:
第二种是通过传递给操作一个新类的对象,java.nio.channels.CompletionHandler,来完成,它会定义在操作完毕后所执行的处理程序方法。------主要做文件系统

第一步,我们要设置服务器
AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(threadGroup);
listener.bind(new InetSocketAddress(listeningAddress, listeningPort));
方法 bind() 将一个套接字地址作为其参数。找到空闲端口的便利方法是传递一个 null 地址,它会自动将套接字绑定到本地主机地址,并使用空闲的 临时 端口。

这个线程池执行两个任务:处理IO事件和
派发CompletionHandler,异步IO操作结果的回调接口,用于定义在IO操作完成后所作的回调工作


第二步:告诉通道接受一个连接
listener.accept(null, new AcceptCompletionHandler()); 这个返回void
或者
listener.accept(); 这个返回Future<AsynchronousSocketChannel>对象。

Future 对象的通用类型是实际操作的结果。比如,读取或写入操作会因为操作返回读或写的字节数,而返回一个 Future<Integer>。
利用 Future 对象,当前线程可阻塞来等待结果:
 
AsynchronousSocketChannel worker = future.get(); 
此处,其阻塞超时时间为 10 秒:
 
AsynchronousSocketChannel worker = future.get(10, TimeUnit.SECONDS); 

第三步:客户端设置
1:接下来,要通过打开并连接与服务器之间的 AsynchronousSocketChannel,来设置客户端:
 
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
    client.connect(server.getLocalAddress()).get();

Socket 

2:通过实现new AcceptCompletionHandler()中的
private class AcceptCompletionHandler implements
   CompletionHandler<AsynchronousSocketChannel, Object> {
  public void completed(AsynchronousSocketChannel channel,
    Object attachment) {
-------------------------
Session session = new AsynchronousSessionImpl(channel,
     configuration, sessionCount);
----------------------------

第四步:通过AsynchronousSocketChannel对象进行read、write操作;
新方法getOption 和 setOption:异步网络通道中查询并设置套接字选项;例如
channel.getOption(StandardSocketOption.SO_RCVBUF) 而不是 channel.socket().getReceiveBufferSize(); 来检索接收缓存大小。

private void initOptions() throws IOException {
  Map<SocketOption<Object>, Object> socketOptionMap = configuration
    .getAllSocketOptions();
  Iterator<Entry<SocketOption<Object>, Object>> it = socketOptionMap
    .entrySet().iterator();
  while (it.hasNext()) {
   Entry<SocketOption<Object>, Object> entry = it.next();
   SocketOption<Object> option = entry.getKey();
   listener.setOption(option, entry.getValue());
 }
}


第五步:实现一个完成处理程序
1:封装了 “ something ” 的 CompletionHandler:扩展CompletionHandler接口,实现completed、failed方法:
private class AcceptCompletionHandler implements
   CompletionHandler<AsynchronousSocketChannel, Object> {
  public void completed(AsynchronousSocketChannel channel,
    Object attachment) {

   try {
    logger.info("Connection accepted(Remote machine:"
      + channel.getRemoteAddress());
   } catch (IOException ex) {
    errLogger.error(ex.getMessage());
   }
   sessionCount++;
   Session session = new AsynchronousSessionImpl(channel,
     configuration, sessionCount);
   sessionMap.put(session.getSessionId(), session);
   try {
    processorFilter.processRequest(session);
   } catch (Exception ex) {
    processorFilter.processException(session, ex);
   }
   listener.accept(null, this);
  }

  public void failed(Throwable ex, Object attachment) {
   errLogger.error("Error occured when accepting connection:");
   errLogger.error(ex.getMessage());
   try {
    stop();
   } catch (IOException e) {
    errLogger.error(ex.getMessage());
  }
 }
}


第六步:异步通道组
java.nio.channels.AsynchronousChannelGroup 中的三个实用方法提供了创建新通道组的方法:
.withCachedThreadPool()---缓存池
And for a cached pool you need:
ExecutorService executor = Executors.newCachedThreadPool();
AsynchronousChannelGroup group =AsynchronousChannelGroup.withCachedThreadPool(executor, 4);
.withFixedThreadPool()---固定池
ExecutorService executor = Executors.newFixedThreadPool(8);
AsynchronousChannelGroup group =AsynchronousChannelGroup.withFixedThreadPool(executor, 8);
.withThreadPool()
ExecutorService executor = // whatever executor type
you want / fixed
cached etc...
AsynchronousChannelGroup group =AsynchronousChannelGroup.withThreadPool(executor);
相单于
ExecutorService executor = Executors.newCachedThreadPool();
AsynchronousChannelGroup group =AsynchronousChannelGroup.withCachedThreadPool(executor, 0);

如 java.util.concurrent.ExecutorService,或者是 java.util.concurrent.ThreadFactory。
如,以下调用创建了具有线程池的新的通道组,该线程池包含 10 个线程,其中每个都构造为来之Executors 类的线程工厂:
AsynchronousChannelGroup threadGroup =
AsynchronousChannelGroup.withFixedThreadPool(threadPoolSize,Executors.defaultThreadFactory());

当有异步操作请求时,此调用告诉 channel 使用 tenThreadGroup 而不是默认通道组来获取线程:
AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(threadGroup);