Java AIO-异步通信

来源:互联网 发布:m1136mfp扫描软件 编辑:程序博客网 时间:2024/05/22 06:46

Java AIO-异步通信

标签: NIO2.0AIO异步非阻塞通信
395人阅读 评论(0)收藏举报
分类:

AIO(Asynchronous IO)即异步IO,特别需要说明的是,JavaAIO需要JDK 1.7的支持

客户端

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.client;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.net.StandardSocketOptions;  
  6. import java.nio.channels.AsynchronousChannelGroup;  
  7. import java.nio.channels.AsynchronousSocketChannel;  
  8. import java.util.concurrent.CountDownLatch;  
  9. import java.util.concurrent.ExecutorService;  
  10. import java.util.concurrent.Executors;  
  11.   
  12. import org.apache.log4j.Logger;  
  13.   
  14. import com.test.handler.client.ConnectCompleteHandler;  
  15.   
  16. public class Client {  
  17.     private Logger logger = Logger.getLogger(Client.class);  
  18.   
  19.     private String host = "127.0.0.1";  
  20.     private int port = 9999;  
  21.     private int poolSize = 10;  
  22.       
  23.     private static CountDownLatch serverStatus = new CountDownLatch(1);  
  24.       
  25.     public Client() throws Exception {  
  26.         try {  
  27.             //池中的每个线程都在等待IO事件,当IO操作完成后,调用池中的线程处理CompleteHandler  
  28.             ExecutorService threadPool = Executors.newFixedThreadPool(poolSize);  
  29.             AsynchronousChannelGroup asyncChannelGroup   
  30.                     = AsynchronousChannelGroup.withThreadPool(threadPool);  
  31.               
  32.             AsynchronousSocketChannel asyncSocketChannel =   
  33.                     AsynchronousSocketChannel.open(asyncChannelGroup);  
  34.             asyncSocketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);  
  35.             asyncSocketChannel.connect(new InetSocketAddress(host, port),   
  36.                     nullnew ConnectCompleteHandler(asyncSocketChannel));  
  37.         } catch (IOException e) {  
  38.             logger.error("Cilent socket establish failed!");  
  39.             throw e;  
  40.         }  
  41.     }  
  42.       
  43.     public static void main(String[] args) throws Exception {  
  44.         Client client = new Client();  
  45.           
  46.         serverStatus.await();  
  47.     }  
  48. }  

客户端处理器

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.handler.client;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.channels.AsynchronousSocketChannel;  
  6. import java.nio.channels.CompletionHandler;  
  7.   
  8. import org.apache.log4j.Logger;  
  9.   
  10. //CompletionHandler<V,A>  
  11. //V-IO操作的结果,AsynchronousSocketChannel.open创建的异步连接,  
  12. //  asyncSocketChannel.connect实际没有IO操作,因此IO操作的结果为Void  
  13. //A-IO操作附件,  
  14. public class ConnectCompleteHandler   
  15.         implements CompletionHandler<Void, Object> {  
  16.     private Logger logger = Logger.getLogger(ConnectCompleteHandler.class);  
  17.       
  18.     AsynchronousSocketChannel asyncSocketChannel;  
  19.       
  20.     public ConnectCompleteHandler(  
  21.             AsynchronousSocketChannel asyncSocketChannel){  
  22.         this.asyncSocketChannel = asyncSocketChannel;  
  23.     }  
  24.       
  25.     @Override  
  26.     public void completed(Void result, Object attachment) {  
  27.         //使用asyncChannelGroup中保存的线程池中的线程进行处理  
  28.         logger.info("Deal thread of [ConnectCompleteHandler] : "   
  29.                 + Thread.currentThread().getName());  
  30.       
  31.         String request = "Hi, this is client!";  
  32.         logger.info("The request sent by client is : " + request);  
  33.         try {  
  34.             byte[] reqBytes = request.getBytes("utf-8");  
  35.             ByteBuffer writeByteBuffer = ByteBuffer.allocate(reqBytes.length);  
  36.             writeByteBuffer.put(reqBytes);  
  37.             writeByteBuffer.flip();  
  38.             asyncSocketChannel.write(writeByteBuffer, asyncSocketChannel,  
  39.                     new WriteCompleteHandler());  
  40.         } catch (UnsupportedEncodingException e) {  
  41.             e.printStackTrace();  
  42.         }  
  43.     }  
  44.   
  45.     @Override  
  46.     public void failed(Throwable exc, Object attachment) {  
  47.         logger.error("Connection error!");  
  48.     }  
  49. }  
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.handler.client;  
  2.   
  3. import java.nio.ByteBuffer;  
  4. import java.nio.channels.AsynchronousSocketChannel;  
  5. import java.nio.channels.CompletionHandler;  
  6.   
  7. import org.apache.log4j.Logger;  
  8.   
  9. //CompletionHandler<V,A>  
  10. //V-IO操作的结果,这里是write操作写成功的字节数  
  11. //A-IO操作附件,这里传入AsynchronousSocketChannel便于获得服务端响应  
  12. public class WriteCompleteHandler   
  13.         implements CompletionHandler<Integer, AsynchronousSocketChannel> {  
  14.     private Logger logger = Logger.getLogger(WriteCompleteHandler.class);  
  15.       
  16.     @Override  
  17.     public void completed(Integer result,   
  18.             AsynchronousSocketChannel asyncSocketChannel) {  
  19.         logger.info("Deal thread of [WriteCompleteHandler] : "   
  20.                 + Thread.currentThread().getName());  
  21.         logger.info("Write bytes : " + result.intValue());  
  22.         if(result.intValue() == -1){  
  23.             logger.error("Send request to server error!");  
  24.         }else{  
  25.             ByteBuffer readByteBuffer = ByteBuffer.allocate(100);  
  26.             //获取服务端发送的响应  
  27.             asyncSocketChannel.read(readByteBuffer, readByteBuffer,   
  28.                     new ReadCompleteHandler());  
  29.         }  
  30.     }  
  31.   
  32.     @Override  
  33.     public void failed(Throwable exc,   
  34.             AsynchronousSocketChannel asyncSocketChannel) {  
  35.         logger.error("Write message error!");  
  36.         exc.printStackTrace();  
  37.     }  
  38. }  
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.handler.client;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.channels.CompletionHandler;  
  6.   
  7. import org.apache.log4j.Logger;  
  8.   
  9. //CompletionHandler<V,A>  
  10. //V-IO操作的结果,这里是read操作成功读取的字节数  
  11. //A-IO操作附件,由于WriteCompleteHandler中调用asyncSocketChannel.read方法时  
  12. //  传入了ByteBuffer,所以这里是ByteBuffer  
  13. public class ReadCompleteHandler   
  14.         implements CompletionHandler<Integer, ByteBuffer> {  
  15.     private Logger logger = Logger.getLogger(ReadCompleteHandler.class);  
  16.       
  17.     @Override  
  18.     public void completed(Integer result, ByteBuffer respByteBuffer) {  
  19.         logger.info("Deal thread of [ReadCompleteHandler] : "   
  20.                 + Thread.currentThread().getName());  
  21.         logger.info("Read bytes : " + result.intValue());  
  22.         if(result.intValue() == -1){  
  23.             logger.error("Get response from server error!");  
  24.         }else{  
  25.             respByteBuffer.flip();  
  26.             byte[] respBytes = new byte[respByteBuffer.remaining()];  
  27.             respByteBuffer.get(respBytes);  
  28.               
  29.             try {  
  30.                 String response = new String(respBytes, "utf-8");  
  31.                 logger.info("The response sent by server is : " + response);  
  32.             } catch (UnsupportedEncodingException e) {  
  33.                 e.printStackTrace();  
  34.             }  
  35.         }  
  36.     }  
  37.   
  38.     @Override  
  39.     public void failed(Throwable exc, ByteBuffer readByteBuffer) {  
  40.         logger.error("Read message error!");  
  41.         exc.printStackTrace();  
  42.     }  
  43. }  

服务端

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.server;  
  2.   
  3. import java.net.InetSocketAddress;  
  4. import java.net.StandardSocketOptions;  
  5. import java.nio.channels.AsynchronousChannelGroup;  
  6. import java.nio.channels.AsynchronousServerSocketChannel;  
  7. import java.nio.channels.AsynchronousSocketChannel;  
  8. import java.util.concurrent.CountDownLatch;  
  9. import java.util.concurrent.ExecutorService;  
  10. import java.util.concurrent.Executors;  
  11. import java.util.concurrent.Future;  
  12.   
  13. import org.apache.log4j.Logger;  
  14.   
  15. import com.test.handler.server.ConnectCompleteHandler;  
  16.   
  17. public class Server {  
  18.     private Logger logger = Logger.getLogger(Server.class);  
  19.       
  20.     private String host = "127.0.0.1";  
  21.     private int port = 9999;  
  22.     private int poolSize = 10;  
  23.       
  24.     private static CountDownLatch serverStatus = new CountDownLatch(1);  
  25.     private AsynchronousServerSocketChannel asyncServerSocketChannel;  
  26.       
  27.     public Server() throws Exception {  
  28.         try{  
  29.             //池中的每个线程都在等待IO事件,当IO操作完成后,触发相应的IO时间,调用池中的线程IO回调函数(CompleteHandler)  
  30.             ExecutorService threadPool = Executors.newFixedThreadPool(poolSize);  
  31.             AsynchronousChannelGroup asyncChannelGroup   
  32.                     = AsynchronousChannelGroup.withThreadPool(threadPool);  
  33.               
  34.             asyncServerSocketChannel = AsynchronousServerSocketChannel.open(asyncChannelGroup);  
  35.             asyncServerSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);  
  36.             asyncServerSocketChannel.bind(new InetSocketAddress(host, port));  
  37.             logger.info("Server start up!");  
  38.         }catch(Exception e){  
  39.             logger.error("Server establish error!");  
  40.             throw e;  
  41.         }  
  42.     }  
  43.   
  44.     public void service(){  
  45. //      这种写法将抛出java.nio.channels.AcceptPendingException异常  
  46. //      只有一个连接建立成功之后,才能再建立下一个连接  
  47. //      while(true){  
  48. //          asyncServerSocketChannel.accept();  
  49. //      }  
  50. //      AIO支持直接返回Future对象,但其实此刻调用并未完成,  
  51. //      while(true){  
  52. //          try {  
  53. //              Future<AsynchronousSocketChannel> acceptFuture = asyncServerSocketChannel.accept();  
  54. ////                wait直到调用完成  
  55. //              AsynchronousSocketChannel asyncSocketChannel = acceptFuture.get();  
  56. //              logger.info("Connection complete!");  
  57. //          } catch (Exception e) {  
  58. //              e.printStackTrace();  
  59. //          }  
  60. //      }  
  61. //      由于asyncChannelGroup的存在,回调是更好的实现方式  
  62.         asyncServerSocketChannel.accept(asyncServerSocketChannel, new ConnectCompleteHandler());  
  63.     }  
  64.       
  65.     public static void main(String[] args) throws Exception {  
  66.         Server server = new Server();  
  67.         server.service();  
  68.           
  69.         //由于AIO的方法都是直接返回的,这里必须使用锁以避免线程退出,服务停止  
  70.         //所谓AIO,既发起请求之后,当前线程可以去干别的事,当请求完成后会得到通知  
  71.         //作为一个全职服务端,main线程其实也没什么别的事情可干,也许还是客户端更加适合使用AIO  
  72.         serverStatus.await();  
  73.     }  
  74. }  

服务端处理器

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.handler.server;  
  2.   
  3. import java.nio.ByteBuffer;  
  4. import java.nio.channels.AsynchronousServerSocketChannel;  
  5. import java.nio.channels.AsynchronousSocketChannel;  
  6. import java.nio.channels.CompletionHandler;  
  7.   
  8. import org.apache.log4j.Logger;  
  9.   
  10. // CompletionHandler<V,A>  
  11. // V-IO操作的结果,这里是成功建立的连接,AsynchronousSocketChannel  
  12. // A-IO操作附件,这里传入AsynchronousServerSocketChannel便于继续接收请求建立新连接  
  13. public class ConnectCompleteHandler   
  14.         implements CompletionHandler<AsynchronousSocketChannel,   
  15.                 AsynchronousServerSocketChannel> {  
  16.       
  17.     private Logger logger = Logger.getLogger(ConnectCompleteHandler.class);  
  18.       
  19.     @Override  
  20.     public void completed(AsynchronousSocketChannel asyncSocketChannel,   
  21.             AsynchronousServerSocketChannel asyncServerSocketChannel) {  
  22.         //使用asyncChannelGroup中保存的线程池中的线程进行处理  
  23.         logger.info("Deal thread of [ConnectCompleteHandler] : "   
  24.                 + Thread.currentThread().getName());  
  25.         //当前连接建立成功后,接收下一个请求建立新的连接  
  26.         asyncServerSocketChannel.accept(asyncServerSocketChannel,  
  27.                 new ConnectCompleteHandler());  
  28.           
  29.         //ByteBuffer是非线程安全的,如果要在多个线程间共享同一个ByteBuffer,需要考虑线程安全性问题  
  30.         ByteBuffer readByteBuffer = ByteBuffer.allocate(100);  
  31.         //获取客户端发送的请求  
  32.         asyncSocketChannel.read(readByteBuffer, readByteBuffer,   
  33.                 new ReadCompleteHandler(asyncSocketChannel));  
  34.     }  
  35.   
  36.     @Override  
  37.     public void failed(Throwable exc, AsynchronousServerSocketChannel attachment) {  
  38.         logger.error("Connection error!");  
  39.     }  
  40. }  
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.handler.server;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.channels.AsynchronousSocketChannel;  
  6. import java.nio.channels.CompletionHandler;  
  7.   
  8. import org.apache.log4j.Logger;  
  9.   
  10. //CompletionHandler<V,A>  
  11. //V-IO操作的结果,这里是read操作成功读取的字节数  
  12. //A-IO操作附件,由于ConnectCompleteHandler中调用asyncSocketChannel.read方法时  
  13. //  传入了ByteBuffer,所以这里为ByteBuffer  
  14. public class ReadCompleteHandler   
  15.         implements CompletionHandler<Integer, ByteBuffer> {  
  16.       
  17.     private Logger logger = Logger.getLogger(ReadCompleteHandler.class);  
  18.     private AsynchronousSocketChannel asyncSocketChannel;  
  19.       
  20.     public ReadCompleteHandler(AsynchronousSocketChannel asyncSocketChannel){  
  21.         this.asyncSocketChannel = asyncSocketChannel;  
  22.     }  
  23.       
  24.     @Override  
  25.     public void completed(Integer result, ByteBuffer readByteBuffer) {  
  26.         logger.info("Deal thread of [ReadCompleteHandler] : "   
  27.                 + Thread.currentThread().getName());  
  28.         logger.info("Read bytes : " + result.intValue());  
  29.         if(result.intValue() == -1){  
  30.             logger.error("Get request from client error!");  
  31.         }else{  
  32.             readByteBuffer.flip();  
  33.             byte[] reqBytes = new byte[readByteBuffer.remaining()];  
  34.             readByteBuffer.get(reqBytes);  
  35.               
  36.             try {  
  37.                 String request = new String(reqBytes, "utf-8");  
  38.                 logger.info("The request sent by client is : " + request);  
  39.               
  40.               
  41.                 String response = "Hi, this is server!";  
  42.                 logger.info("The response has been sent back to client is : "   
  43.                         + response);  
  44.                 byte[] respBytes = response.getBytes("utf-8");  
  45.                 ByteBuffer writeByteBuffer = ByteBuffer.allocate(respBytes.length);  
  46.                 writeByteBuffer.put(respBytes);  
  47.                 writeByteBuffer.flip();  
  48. //              asyncSocketChannel.write(writeByteBuffer);  
  49.                 asyncSocketChannel.write(writeByteBuffer, nullnew WriteCompleteHandler());  
  50.             } catch (UnsupportedEncodingException e) {  
  51.                 e.printStackTrace();  
  52.             }  
  53.         }  
  54.     }  
  55.   
  56.     @Override  
  57.     public void failed(Throwable exc, ByteBuffer readByteBuffer) {  
  58.         logger.error("Read message error!");  
  59.         exc.printStackTrace();  
  60.     }  
  61. }  
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. package com.test.handler.server;  
  2.   
  3. import java.nio.channels.CompletionHandler;  
  4.   
  5. import org.apache.log4j.Logger;  
  6.   
  7. //CompletionHandler<V,A>  
  8. //V-IO操作的结果,这里是write操作写成功的字节数  
  9. //A-IO操作附件,  
  10. public class WriteCompleteHandler   
  11.         implements CompletionHandler<Integer, Object> {  
  12.       
  13.     private Logger logger = Logger.getLogger(WriteCompleteHandler.class);  
  14.       
  15.     @Override  
  16.     public void completed(Integer result, Object attachment) {  
  17.         logger.info("Deal thread of [WriteCompleteHandler] : "   
  18.                 + Thread.currentThread().getName());  
  19.         logger.info("Write bytes : " + result.intValue());  
  20.         if(result.intValue() == -1)  
  21.             logger.info("Send response to client error!" );  
  22.         else  
  23.             logger.info("The response has been sent back to client successfully!" );  
  24.     }  
  25.   
  26.     @Override  
  27.     public void failed(Throwable exc, Object attachment) {  
  28.         logger.error("Write message error!");  
  29.         exc.printStackTrace();  
  30.     }  
  31. }  

log4j日志配置文件

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. log4j.rootLogger=info,logOutput  
  2.   
  3. #log console out put   
  4. log4j.appender.logOutput=org.apache.log4j.ConsoleAppender  
  5. log4j.appender.logOutput.layout=org.apache.log4j.PatternLayout  
  6. log4j.appender.logOutput.layout.ConversionPattern=%p%d{[yy-MM-dd HH:mm:ss]}[%c] -> %m%n  

Server端运行结果

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. INFO[16-08-04 01:20:22][com.test.server.Server] -> Server start up!  
  2. INFO[16-08-04 01:20:26][com.test.handler.server.ConnectCompleteHandler] -> Deal thread of [ConnectCompleteHandler] : pool-1-thread-1  
  3. INFO[16-08-04 01:20:26][com.test.handler.server.ReadCompleteHandler] -> Deal thread of [ReadCompleteHandler] : pool-1-thread-2  
  4. INFO[16-08-04 01:20:26][com.test.handler.server.ReadCompleteHandler] -> Read bytes : 19  
  5. INFO[16-08-04 01:20:26][com.test.handler.server.ReadCompleteHandler] -> The request sent by client is : Hi, this is client!  
  6. INFO[16-08-04 01:20:26][com.test.handler.server.ReadCompleteHandler] -> The response has been sent back to client is : Hi, this is server!  
  7. INFO[16-08-04 01:20:26][com.test.handler.server.WriteCompleteHandler] -> Deal thread of [WriteCompleteHandler] : pool-1-thread-3  
  8. INFO[16-08-04 01:20:26][com.test.handler.server.WriteCompleteHandler] -> Write bytes : 19  
  9. INFO[16-08-04 01:20:26][com.test.handler.server.WriteCompleteHandler] -> The response has been sent back to client successfully!  

Client端运行结果

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. INFO[16-08-04 01:20:26][com.test.handler.client.ConnectCompleteHandler] -> Deal thread of [ConnectCompleteHandler] : pool-1-thread-1  
  2. INFO[16-08-04 01:20:26][com.test.handler.client.ConnectCompleteHandler] -> The request sent by client is : Hi, this is client!  
  3. INFO[16-08-04 01:20:26][com.test.handler.client.WriteCompleteHandler] -> Deal thread of [WriteCompleteHandler] : pool-1-thread-2  
  4. INFO[16-08-04 01:20:26][com.test.handler.client.WriteCompleteHandler] -> Write bytes : 19  
  5. INFO[16-08-04 01:20:26][com.test.handler.client.ReadCompleteHandler] -> Deal thread of [ReadCompleteHandler] : pool-1-thread-3  
  6. INFO[16-08-04 01:20:26][com.test.handler.client.ReadCompleteHandler] -> Read bytes : 19  
  7. INFO[16-08-04 01:20:26][com.test.handler.client.ReadCompleteHandler] -> The response sent by server is : Hi, this is server
0 0
原创粉丝点击