java线程之五 NIO对象

NIO是相对于IO来说的。因为NIO=new IO。从JDK1.4版本以后引进来的。可以说NIO是对IO的补充,

NIO是对IO的进一步封装,解决了原本IO自身堵塞的问题(虽然可以通过线程来解决,但是占用了大量的CPU资源)

简单来说,NIO有缓存Buffer对象,通过Channel来存储和读写Buffer。提供了Charset对象来实现Unicode与其他字符间

的转换,最后通过Selector来完成非堵塞开发。

关于NIO与IO区别 可以参考以下文章

http://www.dewen.org/q/9648

http://tutorials.jenkov.com/java-nio/nio-vs-io.html

下班了,直接上代码

服务端代码

  1 /**
  2  * @author draem0507@gmail.com
  3  * @TODO java 线程之五 nio nio介绍 在1.4以后的JDK中出现了new io 特性主要表现在 1.非阻塞(不用单独开线程来模拟)
  4  *       2.字符转换 3.缓冲及其通道 新增了四个重要的类 1.Buffer 缓冲区 2.Charset 提供了Unicode与其他字符编码之间的转换
  5  *       3.Channel 数据传输通道 将Buffer的数据进行写入或则读取 4.Selector 用来支持异步的I/O操作
  6  *       参考资料:http://blog.chinaunix.net/uid-24186189-id-2623973.html
  7  * @version 1.0
  8  * @date 2013-5-8 15:26:45
  9  * @blgos http://www.cnblogs.com/draem0507
 10  */
 11 public class ServerTest {
 12     private ByteBuffer _buffer = ByteBuffer.allocate(16);
 13     private IntBuffer _intBuffer = _buffer.asIntBuffer();
 14     private SocketChannel clientChannel;
 15     private ServerSocketChannel serverSocketChannel;
 16 
 17     public ServerTest() {
 18     }
 19 
 20     private void startServer() {
 21         openConnection();
 22         listenConnection();
 23 
 24     }
 25 
 26     private void listenConnection() {
 27         // 单线程模拟
 28 
 29         /*
 30          * while (true) { try { clientChannel = serverSocketChannel.accept(); if
 31          * (null != clientChannel) { System.out.println("新的客户端连接"); // 进行请求操作
 32          * Thread.sleep(5000);
 33          * 
 34          * doRequest(); // 关闭socket clientChannel.close(); } } catch
 35          * (IOException e) { // TODO Auto-generated catch block
 36          * e.printStackTrace(); } catch (InterruptedException e) { // TODO
 37          * Auto-generated catch block e.printStackTrace(); }
 38          *  }
 39          */
 40         // 多线程模式
 41         // openConnection方法中开启非堵塞模式
 42         // 引入selector
 43         try {
 44             Selector selector = SelectorProvider.provider().openSelector();
 45             // 注册selector对象到套接字对象并设置为accept 告诉selector套接字对象操作I/O时希望使用非堵塞模式
 46             SelectionKey key = serverSocketChannel.register(selector,
 47                     SelectionKey.OP_ACCEPT);
 48             int addKey = 0;
 49             while ((addKey = selector.select()) > 0) {
 50 
 51                 Set readyKeys = selector.selectedKeys();
 52                 Iterator i = readyKeys.iterator();
 53                 // 遍历ready键集合,并处理加法请求
 54                 while (i.hasNext()) {
 55                     SelectionKey sk = (SelectionKey) i.next();
 56                     i.remove();
 57                     ServerSocketChannel nextReady = (ServerSocketChannel) sk
 58                             .channel();
 59                     // 接受加法请求并处理它
 60                     clientChannel = nextReady.accept();
 61                     //为了方便测试 这里加入时间
 62                     
 63                     Thread.sleep(5000);
 64                     doRequest();
 65                     clientChannel.close();
 66                 }
 67             }
 68         } catch (IOException e) {
 69             // TODO Auto-generated catch block
 70             e.printStackTrace();
 71         } catch (InterruptedException e) {
 72             // TODO Auto-generated catch block
 73             e.printStackTrace();
 74         }
 75 
 76     }
 77 
 78     private void doRequest() {
 79         _buffer.clear();
 80         try {
 81             clientChannel.read(_buffer);
 82             int req = _intBuffer.get(0);
 83             _buffer.flip();
 84             _buffer.clear();
 85             _intBuffer.put(0, req * 2);
 86             clientChannel.write(_buffer);
 87 
 88         } catch (IOException e) {
 89             // TODO Auto-generated catch block
 90             e.printStackTrace();
 91         }
 92 
 93     }
 94 
 95     private void openConnection() {
 96         try {
 97             serverSocketChannel = ServerSocketChannel.open();
 98             // new ServerSocket(10000);内部也是实现了bind 间接说明NIO是在IO的基础上进行了封装
 99             // 而不同的地方不在于如何创建对象 而是对象的读取写入(缓存)监听客户端连接的方式(selector)等区别
100             serverSocketChannel.socket().bind(new InetSocketAddress(10000));
101             // 非堵塞模式 开关默认
102             serverSocketChannel.configureBlocking(false);
103 
104             System.out.println("服务器已经开始连接");
105         } catch (IOException e) {
106             // TODO Auto-generated catch block
107             e.printStackTrace();
108         }
109 
110     }
111 
112     public static void main(String[] args) {
113         new ServerTest().startServer();
114     }
115 
116 }

客户端代码

 1 public class ClientTest {
 2     private SocketChannel channel;
 3     private ByteBuffer _buffer=ByteBuffer.allocate(16);
 4     private IntBuffer _intBuffer=_buffer.asIntBuffer();
 5 
 6     public ClientTest() {
 7     }
 8 
 9     private void conn() {
10 
11         connServer();
12         sendRequest();
13         int resp=receiveRequest();
14         System.out.println("收到服务端的结果:"+resp);
15 
16     }
17 
18     private int  receiveRequest() {
19         _buffer.clear();
20         try {
21             channel.read(_buffer);
22         } catch (IOException e) {
23             // TODO Auto-generated catch block
24             e.printStackTrace();
25         }
26         return _intBuffer.get(0);
27         
28     }
29 
30     private void sendRequest() {
31         
32         _buffer.clear();
33         int send=(int)(Math.random()*5)+1;
34         _intBuffer.put(0, send);
35         try {
36             channel.write(_buffer);
37         } catch (IOException e) {
38             // TODO Auto-generated catch block
39             e.printStackTrace();
40         }
41         System.out.println("发送数据:"+send);
42         
43     }
44 
45     private void connServer() {
46         InetSocketAddress remote = new InetSocketAddress("localhost", 10000);
47         try {
48             channel=SocketChannel.open(remote);
49         } catch (IOException e) {
50             // TODO Auto-generated catch block
51             e.printStackTrace();
52         }
53     }
54 
55     public static void main(String[] args) {
56         new ClientTest().conn();
57     }
58 
59 }
原文地址:https://www.cnblogs.com/draem0507/p/3067259.html