zoukankan      html  css  js  c++  java
  • java nio纯理论

    NIO之前:如果你需要编写一个Java服务器,为了实现异步操作,你必须为每个连接请求生成一个Java线程,当连接请求很多时,线程的调度,上下文切换,所付出的 代价是非常昂贵,而且由于Java是跨平台的,各个平台对线程的支持并不相同,性能也不相同,因此传统的Java服务器编程架构是低效的且代价贵,dl大 侠写了个util.concurrent包后,总算是减轻了线程调度给java程序员带来的痛苦,但是相比之与C、C++写出来的服务器,java服务器 在性能要求很高的情况下,基本上没有什么竞争力,甚至是入围的权利的都没有

    NIO是一个基于事件的IO架构,最基本的思想就是:有事件我通知你,你再去做你的事情,没事件时你大可以节约大把时间去做其它任何事情。而且NIO的主线程only one,不像传统的模型,需要N个线程去,也减轻了JVM的工作量,使得JVM处理任务时显得更加高效。

    三、 异步Socket中应当注意的事情

    1. 读

    异步socket最基本的理念就是事件通知,前面也说了,有事件通知你了,你才该做你应当做的事情。在异步socket中当注册了一个OP_READ事件后,你就等着Selector通知你吧,如果没有通知你,你在家睡大觉都行。
    在这里,我们有人出现的错误就是受同步的影响,自己去主动读,而且还搞出了多线程,如果仔细考虑一下,就不会出现这个问题了。同步socket中,调用 read方法读取IO中的数据时,通常情况下如果没有数据read方法会阻塞,且是同步的,所以当多个线程同时访问时,read方法是线程安全的。

    而在异步下就不同,异步是不会阻塞的,有什么就返回什么,你主动去读,只要有数据,你就可以拿走,在多线程的情况下,也许你是想让第一个线程读 取,but此时来数据时正好是线程2读到了,那线程2就高高兴兴的拿去,而线程1还在苦苦等待,这样导致数据混乱不说,如果后面再也不来数据了,线程1就 是死循环啦。

    2. 写

    在异步socket中,写是唯一一个主动点的操作,但是也不能直接去写Channel,而是应当先把自身注册为OP_WRITABLE,这时 Selector就会发现你的存在,并把给发一个write事件,你这时后就可以写了,不过这时候有个小小的技巧,就是你执行写操作之前,请取消掉你的写 注册,否则你的cpu肯定是100%。

    3. 等待

    在传统的服务器编程中,由于对于每个请求都是产生的一个线程,因此你在你每个请求线程中wait也好,sleep也好,不会影响别人。但是异步不 同,他的主线程只有一个,基本上每个处理都是线性的,也就是说处理完第一个,然后才能处理第二个,因此nio是一个极好的处理短连接的架构。

    我们现在出现的问题是,有人受同步的影响,没有搞清异步是如何处理,竟然在方法处理中用上sleep,而且一等还是3秒,这意味着什么,3秒才能处理一个请求,My god,我要一个3秒才能处理一个请求的服务器干嘛啊,还是60年代啊:(

    如果出现这样的需要等待的情况,应当另起一个线程(推荐使用线程池)去完成这个“长”时间的任务,或者将其它交给一个消息队列,通过发消息的方式将给别人去完成也行,客户端能等,你服务器怎么也能等呢?写出这样的代码,基本上一个服务器也就废了。

    java.nio.Buffer的一些基础知识的备忘

    capacity(): 表明缓冲区的容量大小, 一旦确定了大小, 将不能再改变;
    limit(): 告诉您到目前为止已经往缓冲区填了多少字节,或者用#limit(int)来改变这个限制;
    position(): 告诉您当前的位置,以执行下一个读/写操作;
    mark(): 为了稍后用 reset() 进行重新设置而记住某个位置;
    flip(): 交换限制指针和位置指针,然后将位置置为 0,并废弃已经做的mark标记。

    缓冲区的基本操作是读#get()和写#put()。

    缓冲区类型:

    NIO具有7种特定的 Buffer 类型,每种类型对应着一个基本数据类型(除了 boolean)

    1. ByteBuffer //字节缓冲区 
    2. CharBuffer //字符缓冲区 
    3. DoubleBuffer //double 缓冲区 
    4. FloatBuffer //float 缓冲区 
    5. IntBuffer //int 缓冲区 
    6. LongBuffer //long 缓冲区 
    7. ShortBuffer //short 缓冲区 

    缓冲区分为直接缓冲区和间接缓冲区,直接缓冲区的创建成本要高于间接缓冲区,但同时它也会提供更快的I/O访问速度。所以直接缓冲区适合那种长期存在的缓冲区,而间接缓冲区则适合于生命周期较短的。还有,要注意,只有ByteBuffer可以创建直接缓冲区。

    缓冲区的几个内部状态的改变:

    容量(capacity),缓冲区大小

    限制(limit),第一个不应被读取或写入的字节的索引,总是小于容量。

    位置(position),下一个被读取或写入的字节的索引,总是小于限制。

    0 <= position <= limit <= capacity

    1. clear()方法:设置limit为capacity,position为0,并丢弃mark。

    2. filp()方法:设置limit为当前position,然后设置position为0,并丢弃mark。

    3. rewind()方法:保持limit不变,设置position为0,并丢弃mark。

    Top
    收藏
    关注
    评论
  • 相关阅读:
    pandas Dataframe filter
    process xlsx with pandas
    data manipulate in excel with easyExcel class
    modify registry in user environment
    add number line in vim
    java import webservice
    ctypes MessageBoxA
    music 163 lyrics
    【python实例】自动贩卖机
    【python基础】sys模块(库)方法汇总
  • 原文地址:https://www.cnblogs.com/momofan/p/2882775.html
Copyright © 2011-2022 走看看