Netty源碼分析第二章:NioEventLoophtml
第三節:初始化線程選擇器java
回到上一小節的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分配不一樣的線程ide
咱們看到newChooser(children)傳入了NioEventLoop數組
oop
咱們跟到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的倍數, 則使用一種比較普通的線程選擇方式this
咱們簡單跟進這兩種策略的選擇器對象中看一下, 首先看一下PowerOfTowEventExecutorChooser這個類:spa
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的倍數, 則用絕對值和取模的這種效率通常的方式進行線程選擇
這樣, 咱們就初始化了線程選擇器對象