leader-follower模型

解决的方案是使用Leader-Follower线程模型,它的基本思想是所有的线程被分配成两种角色:
Leader和Follower,一般同时只有一个Leader线程,所有的Follower线程排队等待成为Leader线程,线程池启动时自动产生一个Leader负责等待网络IO事件,当有一个事件产生时,Leader线程首先通知一个Follower线程,并将其提拔为新的Leader,然后自己去处理这个网络事件,处理完毕后加入Follower线程等待队列,等待重新成为Leader.

这个线程模型主要解决了内存的动态分配问题,我们不需要不断的将到来的网络IO事件放入队列,并且等待网络IO事件的线程在等到网络事件的发生后,是自己处理的这个事件,也就是说没有context switching的过程.

首先定义我们的事件模型Event
public interface Event {  
    SelectableChannel getChannel();  
} 

它的实现:
public class DefaultEventImpl implements Event {  
    private SelectableChannel channel;  
  
    public DefaultEventImpl(SelectableChannel channel) {  
        this.channel = channel;  
    }  
  
    @Override  
    public SelectableChannel getChannel() {  
        return this.channel;  
    }  
}  

然后定义我们的EventHandler
public interface EventHandler {  
    /** 
     * this can be blocked 
     *  
     * @return Event 
     */  
    Event pollEvent();  
  
    void handleEvent(Event e);  
}  

其中的pollEvent()方法会阻塞,当有网络请求时返回一个我们封装的Event对象,其实里面大体上就是select()方法

接下来是我们的核心部分,Leader-Follower线程池的定义
public interface LFThreadPool {  
    void start();  
  
    void promoteLeader();  
  
    void waitToBeLeader();  
}  

通过start方法启动线程池,然后调用一次promoteLeader产生了一个Leader线程等待网络事件的到达,其余线程则是waitToBeLeader的状态.

我们还定义了一个Worker线程模型
public interface WorkerThread extends Runnable {  
    void start();  
} 

start方法主要是启动所有的workers,其实觉得可以省去这个接口的


然后看一下我们的worker thread实现
public class DefaultWorkerThread implements WorkerThread {  
    private LFThreadPool pool;  
    private EventHandler handler;  
    private boolean isActive;  
  
    public DefaultWorkerThread(DefaultLFThreadPoolImpl pool,  
            EventHandler handler) {  
        this.pool = pool;  
        this.handler = handler;  
    }  
  
    @Override  
    public void run() {  
        while (isActive) {  
            this.pool.waitToBeLeader();  
           //阻塞等待pollEvent返回待处理的事件,此处等待的是Leader线程  
            Event event = handler.pollEvent();  
           //notify 唤醒一个正在等待的线程成为leader,由它来等待新的  
           //网络事件到达,自己则去处理当前的IO事件  
            this.pool.promoteLeader();  
  
            handler.handleEvent(event);  
           //处理完毕后you重新waitToBeLeader等待成为Leader  
        }  
    }  
  
    @Override  
    public synchronized void start() {  
        if (!isActive) {  
            isActive = true;  
        }  
        new Thread(this).start();  
    }  
  
}  

最后是我们的线程池的实现部分,看一下LFThreadPool的实现
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);  
        }  
    }  
  
    @Override  
    public synchronized void start() {  
  
        if (!isActive) {  
           //启动所有的workers  
            for (int i = 0; i < workers.length; i++) {  
                workers[i].start();  
            }  
            //保证所有的workers已经启动  
            try {  
                Thread.sleep(100);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            //产生一个Leader线程  
            promoteLeader();  
  
            isActive = true;  
        }  
    }  
  
    @Override  
    public void promoteLeader() {  
        synchronized (semaphore) {  
            semaphore.notify();  
        }  
    }  
  
    @Override  
    public void waitToBeLeader() {  
        synchronized (semaphore) {  
            try {  
                semaphore.wait();  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
}  

猜你喜欢

转载自boisterous.iteye.com/blog/940200