zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    MySQL之自增长
    MySQL字符集和校对规则
    关于MySQL安装目录bin下工具的详解
    Linux下载安装配置FTP
    Linux和Windows平台安装MySQL的两种方式
    kali安装linux-header
    Mysql之事务
    Linux之ps命令
    Linux之dd命令
    python爬虫之xpath的基本使用
  • 原文地址:https://www.cnblogs.com/draem0507/p/3067259.html
Copyright © 2011-2022 走看看