http://www.iteye.com/topic/1112123
http://dongxuan.iteye.com/blog/901689
http://scholers.iteye.com/blog/1452780
基本流程
1、服务端监听端口是否有连接建立,接收到请求,创建IoSession
2、IoProcessor轮训IO通道,处理IO操作(读写),从线程池调用IoHandler线程处理工作
3、IoHandler处理工作
几个主要的概念:
1、线程
Mina2中在三个地方使用了线程:
IoAcceptor接收客户端的连接建立,每监听一个端口(调一次bind()方法)启用一个线程;每接收到一次请求,创建一个IoSession对象,因为创建IoSession对象的速度足够快,所以一个线程就够了。
IoConnector用于与服务端建立连接,每连接一个服务器(调用一次connect()方法),创建一个IoSession对象。
真正执行IO操作的线程,默认启用的线程数是CPU和核数+1,如单CPU双核电脑,默认的IoProcessor就会创建3个,也就是说一个IoAcceptor/IoConnector会关联一个 IoProcessor池,这个池中有3个IoProcessor。
为什么IoProcessor比CPU核数大一?因为IO操作耗费资源。但是一般实现的时候都采用工作线程与IO线程分离,并且现在的CPU性能已经大大的提升了,所以可以根据实际配置适当增加。如:netty中默认为cpu个数*2+1。
IoProcessor的构造方法有一个参数是java.util.concurrent.Executor,这个参数就是让IO线程与工作线程分离的关键,也就是让IoProcessor调用的IoHandler中的某些方法(MessageReceived()等)在线程池中分配的线程独立运行,而不是在IoProcessor所在的线程。即:acceptor.getFilterChain().addLast(“threadpool”, new ExcetorFilter());这行代码设置的如果不指定ExcetorFilter参数,默认使用OrderedThreadPoolExecutor
2、线程队列
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,排队有三种通用策略: