mina2 笔记

http://www.iteye.com/topic/1112123java

http://dongxuan.iteye.com/blog/901689服务器

http://scholers.iteye.com/blog/1452780多线程

 

基本流程性能

一、服务端监听端口是否有链接创建,接收到请求,建立IoSessionspa

二、IoProcessor轮训IO通道,处理IO操做(读写),从线程池调用IoHandler线程处理工做操作系统

三、IoHandler处理工做线程

几个主要的概念
一、线程
Mina2中在三个地方使用了线程:netty

  • IoAcceptor/IoConnector线程

  IoAcceptor接收客户端的链接创建,每监听一个端口(调一次bind()方法)启用一个线程;每接收到一次请求,建立一个IoSession对象,由于建立IoSession对象的速度足够快,因此一个线程就够了。code

    IoConnector用于与服务端创建链接,每链接一个服务器(调用一次connect()方法),建立一个IoSession对象。对象

  • IoProcessor线程

  真正执行IO操做的线程,默认启用的线程数是CPU和核数+1,如单CPU双核电脑,默认的IoProcessor就会建立3个,也就是说一个IoAcceptor/IoConnector会关联一个    IoProcessor池,这个池中有3个IoProcessor。

  为何IoProcessor比CPU核数大一?由于IO操做耗费资源。可是通常实现的时候都采用工做线程与IO线程分离,而且如今的CPU性能已经大大的提高了,因此能够根据实际配置适当增长。如:netty中默认为cpu个数*2+1。

  • IoHandler线程

  IoProcessor的构造方法有一个参数是java.util.concurrent.Executor,这个参数就是让IO线程与工做线程分离的关键,也就是让IoProcessor调用的IoHandler中的某些方法(MessageReceived()等)在线程池中分配的线程独立运行,而不是在IoProcessor所在的线程。即:acceptor.getFilterChain().addLast(“threadpool”, new ExcetorFilter());这行代码设置的若是不指定ExcetorFilter参数,默认使用OrderedThreadPoolExecutor

 

二、线程队列

  OrderedThreadPoolExecutor等*Executor都是是继承自ThreadPoolExecutor,区别在于队列大小、队列类型上。IoAcceptor实现NioSocketAcceptor默认用的是ExecutorService.newCachedThreadPool(),这是一个无界的线程池,而且队列是一个同步队列。

代码以下:

public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }

ThreadPoolExecutor共有6个构造参数:

  corePoolSize:线程池维护线程的最少数量

  maximumPoolSize:线程池维护线程的最大数量

   keepAliveTime:线程池维护线程所容许的空闲时间

   unit:线程池维护线程所容许的空闲时间的单位

   workQueue:线程池所使用的缓冲队列

    handler:线程池对拒绝任务的处理策略

排队规则:

  A. 若是运行的线程少于corePoolSize,则Executor始终首选添加新的线程,而不进行排队。

  B.  若是运行的线程等于或多于corePoolSize,则Executor始终首选将请求加入队列,而不添加新的线程。

  C.  若是没法将请求加入队列,则建立新的线程,除非建立此线程超出maximumPoolSize,在这种状况下,任务将被拒绝。

 

对于workQueue,排队有三种通用策略:

  1. 直接提交工做队列的默认选项是 SynchronousQueue,它将任务直接提交给线程而不保持它们。在此,若是不存在可用于当即运行任务的线程,即线程池已达到maximumPoolSizes,则试图把任务加入队列将失败。此策略保证先来的请求先处理,能够避免在处理可能具备内部依赖性的请求集时出现锁。直接提交一般要求无界 maximumPoolSizes 以免拒绝新提交的任务。
  1. 无界队列使用无界队列将致使在全部 corePoolSize 线程都忙时新任务在队列中等待。这样,建立的线程就不会超过 corePoolSize。(结果是maximumPoolSize 的值无效了)。当每一个任务彻底独立于其余任务,即任务执行互不影响时,适合于使用无界队列;例如,在 Web 页服务器中。这种排队可用于处理瞬态突发请求。
  1. 有界队列当使用有限的 maximumPoolSizes 时,有界队列(如 ArrayBlockingQueue)有助于防止资源耗尽,缺点是较难调整和控制,JDK并不推荐使用这种方式。队列大小和最大池大小可能须要相互折衷:使用大型队列和小型池能够最大限度地下降 CPU 使用率、操做系统资源和上下文切换开销,可是可能致使人工下降吞吐量。若是任务频繁阻塞(例如,若是它们是 I/O 边界),则系统可能为超过您许可的更多线程安排时间。使用小型队列一般要求较大的池大小,CPU 使用率较高,可是可能遇到不可接受的调度开销,这样也会下降吞吐量。
相关文章
相关标签/搜索