1. 程式人生 > >Netty原始碼分析第2章(NioEventLoop)---->第3節: 初始化執行緒選擇器

Netty原始碼分析第2章(NioEventLoop)---->第3節: 初始化執行緒選擇器

 

第二章:NioEventLoop

 

第三節:初始化執行緒選擇器

回到上一小節的MultithreadEventExecutorGroup類的構造方法:

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, 
                                        EventExecutorChooserFactory chooserFactory, Object... args) {
    //程式碼省略
    if (executor == null
) { //建立一個新的執行緒執行器(1) executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); } //構造NioEventLoop(2) children = new EventExecutor[nThreads]; for (int i = 0; i < nThreads; i ++) { boolean success = false; try { children[i] = newChild(executor, args); success
= true; } catch (Exception e) { throw new IllegalStateException("failed to create a child event loop", e); } finally { //程式碼省略 } } //建立執行緒選擇器(3) chooser = chooserFactory.newChooser(children); //程式碼省略 }

我們看第三步, 建立執行緒選擇器:

chooser = chooserFactory.newChooser(children);

NioEventLoop都繫結一個chooser物件, 作為執行緒選擇器, 通過這個執行緒選擇器, 為每一個channel分配不同的執行緒

我們看到newChooser(children)傳入了NioEventLoop陣列, 我們跟到方法中去, 我們跟到了DefaultEventExecutorChooserFactory類中的newChooser方法:

public EventExecutorChooser newChooser(EventExecutor[] executors) { 
    if (isPowerOfTwo(executors.length)) { 
        return new PowerOfTowEventExecutorChooser(executors);
    } else {
        return new GenericEventExecutorChooser(executors);
    }
}

這裡通過isPowerOfTwo(executors.length)判斷NioEventLoop的執行緒數是不是2的倍數, 然後根據判斷結果返回兩種選擇器物件, 這裡使用到java設計模式的策略模式

根據這兩個類的名字不難看出, 如果是2的倍數, 使用的是一種高效能的方式選擇執行緒, 如果不是2的倍數, 則使用一種比較普通的執行緒選擇方式

我們簡單跟進這兩種策略的選擇器物件中看一下, 首先看一下PowerOfTowEventExecutorChooser這個類:

private static final class PowerOfTowEventExecutorChooser implements EventExecutorChooser {
    private final AtomicInteger idx = new AtomicInteger();
    private final EventExecutor[] executors;
    PowerOfTowEventExecutorChooser(EventExecutor[] executors) {
        this.executors = executors;
    }
    @Override
    public EventExecutor next() {
        return executors[idx.getAndIncrement() & executors.length - 1];
    }
}

這個類實現了執行緒選擇器的介面EventExecutorChooser, 構造方法中初始化了NioEventLoop執行緒陣列

重點關注下next()方法, next()方法就是選擇下一個執行緒的方法, 如果執行緒數是2的倍數, 這裡通過按位與進行計算, 所以效率極高

再看一下GenericEventExecutorChooser這個類:

private static final class GenericEventExecutorChooser implements EventExecutorChooser {
    private final AtomicInteger idx = new AtomicInteger();
    private final EventExecutor[] executors;
    GenericEventExecutorChooser(EventExecutor[] executors) {
        this.executors = executors;
    }
    @Override
    public EventExecutor next() {
        return executors[Math.abs(idx.getAndIncrement() % executors.length)];
    }
}

這個類同樣實現了執行緒選擇器的介面EventExecutorChooser, 並在造方法中初始化了NioEventLoop執行緒陣列

再看這個類的next()方法, 如果執行緒數不是2的倍數, 則用絕對值和取模的這種效率一般的方式進行執行緒選擇

 

這樣, 我們就初始化了執行緒選擇器物件

 

 

回到上一小節的MultithreadEventExecutorGroup類的構造方法: