Leader Follower线程模型简单实现
在我们编写网络服务程序时,比较简单的方式是per client per thread模型,这种模型当客户端连接数快速增长是就会出现性能瓶颈,我们不能不断的开启新的线程,当然我们肯定是会使用线程池,但是线程的管理和频繁的线程调度也会影响性能.
java 1.4给我们带来了NIO编程模型,由于它的读写操作都是无阻塞的,这样使我们能够只用一个线程处理所有的IO事件,当然我们不会真的只用一个线程来处理,比较常见的编写NIO网络服务程序的模型是半同步-半异步模式,其实现原理大体上是单线程同步处理网络IO请求,当有请求到达时,将该请求放入一个工作队列中,由另外的线程处理,主线程继续等待新的网络IO请求,这种编程模型的缺点主要是:
1.使用工作队列带来的内存的动态分配问题
2.每次网络IO请求,总是分配给另外一个线程处理,这样频繁的线程的context switching也会 影响性能
解决的方案是使用Leader-Follower线程模型,它的基本思想是所有的线程被分配成两种角色:
Leader和Follower,一般同时只有一个Leader线程,所有的Follower线程排队等待成为Leader线程,线程池启动时自动产生一个Leader负责等待网络IO事件,当有一个事件产生时,Leader线程首先通知一个Follower线程,并将其提拔为新的Leader,然后自己去处理这个网络事件,处理完毕后加入Follower线程等待队列,等待重新成为Leader.
这个线程模型主要解决了内存的动态分配问题,我们不需要不断的将到来的网络IO事件放入队列,并且等待网络IO事件的线程在等到网络事件的发生后,是自己处理的这个事件,也就是说没有context switching的过程.
下面是简单的代码演示
首先定义我们的事件模型Event
public class DefaultLFThreadPoolImpl implements LFThreadPool {private WorkerThread[] workers;private boolean isActive;private Object semaphore = new Object();public DefaultLFThreadPoolImpl(int poolSize, EventHandler handler) {workers = new DefaultWorkerThread[poolSize];for (int i = 0; i < poolSize; i++) {workers[i] = new DefaultWorkerThread(this, handler);}}@Overridepublic synchronized void start() {if (!isActive) { //启动所有的workersfor (int i = 0; i < workers.length; i++) {workers[i].start();} //保证所有的workers已经启动try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();} //产生一个Leader线程promoteLeader();isActive = true;}}@Overridepublic void promoteLeader() {synchronized (semaphore) {semaphore.notify();}}@Overridepublic void waitToBeLeader() {synchronized (semaphore) {try {semaphore.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}
整个过程中没有动态内存分配,也没有频繁的context switching,应该可以提高部分效率,后续会发出完整的程序,欢迎大家指正.
1 楼 anranran 2011-08-10 好文,代码不全,可否补全 2 楼 anranran 2011-08-10 Event event = handler.pollEvent();
这地方就有线程切换