jdk源码分析 ——Selector深入分析
2018-01-20 15:46
316 查看
1、spi方式的selector定制化
selector通过SelectorProvider创建的,通常不同安装版本的jdk中已经封装了相应的Select和SelectorProvider了,通过spi的方式进行扩展。(PS:spi是一种jdk提供的低侵入方式的扩展实现,目前已经在大多数的框架中使用了,类似dubbo框架也使用该方式,让用户进行更好的定制化实现)
2、selector的原理
NIO极大提高了IO的并发,且在各大操作系统都已经有了相应的支持,类似linux的select、pool、epoll等,windows的IOCP等。在NIO中又包含了两种机制,一种是reactor;另外一种是proactor,这两种方式的主要区别是:IO数据是自己去内核读取,还是提供用户空间数据缓冲区,让内核读取。
在目前的jdk版本中也最大化的利用了操作系统的NIO机制,封装成了统一的接口供java应用使用,该实现机制是在操作系统的NIO的reactor或者proactor机制之上,再次封装了一次,并创建相应的socket事件的映射即可。
3、selector多线程特性
在jdk中自带的selector的方法是线程安全的,可以多线程调用selector的方法,但是从我个人的实践来看,其实没有必要多线程调用,其实单个线程就可以了,最主要是select出来的Set这个可以进行多线程的处理,但是该集合是非线程安全的,所以在多线程使用的时候需要进行同步的操作。
4、关于多线程accept的理解
为什么需要多线程的accept?这个问题需要仔细的分析,目前很多框架都是用了多线程的accept,但是使用多线程的accept是有条件的,那就是在某一个线程accept之后之后,会对新的socket进行一些简单的认证的操作等,操作完了之后再把该socket放入业务线程池。由于这些操作需要花费一定的时间,所以这个时候可以把serversocket让出来,让其他的线程accept。
那么问题来了:那为什么不可以单个线程accept,然后将accept的socket直接丢到业务线程池呢?
其实这样也是可以的,但是为了更好的符合单一职责的原则,业务线程池应该是主要负责业务处理的,那么像socket的一些合法性检测等操作应该使用单独的线程池进行,既然有了独立的线程池,而且这些检测本身也不是特别耗时,所以就可以把accept也放到该线程中了。
但是在很早之前的操作系统中这种多线程的accept会出现“惊群”效应,目前很多操作系统已经解决了。
selector通过SelectorProvider创建的,通常不同安装版本的jdk中已经封装了相应的Select和SelectorProvider了,通过spi的方式进行扩展。(PS:spi是一种jdk提供的低侵入方式的扩展实现,目前已经在大多数的框架中使用了,类似dubbo框架也使用该方式,让用户进行更好的定制化实现)
2、selector的原理
NIO极大提高了IO的并发,且在各大操作系统都已经有了相应的支持,类似linux的select、pool、epoll等,windows的IOCP等。在NIO中又包含了两种机制,一种是reactor;另外一种是proactor,这两种方式的主要区别是:IO数据是自己去内核读取,还是提供用户空间数据缓冲区,让内核读取。
在目前的jdk版本中也最大化的利用了操作系统的NIO机制,封装成了统一的接口供java应用使用,该实现机制是在操作系统的NIO的reactor或者proactor机制之上,再次封装了一次,并创建相应的socket事件的映射即可。
3、selector多线程特性
在jdk中自带的selector的方法是线程安全的,可以多线程调用selector的方法,但是从我个人的实践来看,其实没有必要多线程调用,其实单个线程就可以了,最主要是select出来的Set这个可以进行多线程的处理,但是该集合是非线程安全的,所以在多线程使用的时候需要进行同步的操作。
4、关于多线程accept的理解
为什么需要多线程的accept?这个问题需要仔细的分析,目前很多框架都是用了多线程的accept,但是使用多线程的accept是有条件的,那就是在某一个线程accept之后之后,会对新的socket进行一些简单的认证的操作等,操作完了之后再把该socket放入业务线程池。由于这些操作需要花费一定的时间,所以这个时候可以把serversocket让出来,让其他的线程accept。
那么问题来了:那为什么不可以单个线程accept,然后将accept的socket直接丢到业务线程池呢?
其实这样也是可以的,但是为了更好的符合单一职责的原则,业务线程池应该是主要负责业务处理的,那么像socket的一些合法性检测等操作应该使用单独的线程池进行,既然有了独立的线程池,而且这些检测本身也不是特别耗时,所以就可以把accept也放到该线程中了。
但是在很早之前的操作系统中这种多线程的accept会出现“惊群”效应,目前很多操作系统已经解决了。
相关文章推荐
- Java容器深入研究(jdk 1.8)--- ArrayList总结与源码分析
- Selector源码深入分析之Window实现(下篇)
- Selector源码深入分析之Window实现(上篇)
- TreeMap源码分析——深入分析(基于JDK1.6)
- TreeMap源码分析——深入分析(基于JDK1.6)
- jdk的Selector源码分析(一)Selector概述
- Java中ArrayList源码深入分析(JDK1.6)
- jdk的Selector源码分析(二)poll方式实现
- 深入理解Spark 2.1 Core (十一):Shuffle Reduce 端的原理与源码分析
- [jjzhu学java]之JDK集合框架源码分析
- 参照JDK源码实现一个LinkedList,分析常用的List集合及其适用场景
- 【集合框架】JDK1.8源码分析之HashMap(一)
- Java源码分析:深入探讨Iterator模式
- Solr4.8.0源码分析(16)之SolrCloud索引深入(3)
- java源码分析之HashMap(jdk1.6)
- Retrofit源码分析 (六. Retrofit 深入ParameterHandler及其他)
- JDK源码分析(四)——LinkedHashMap
- Java集合框架成员之LinkedList类的源码分析(基于JDK1.8版本)
- Java异步编程——深入源码分析FutureTask
- 深入源码分析TreeSet和TreeMap