與JAVA Executor的區別
vertx框架提供了OrderedExecutor的實現,其能保證提交的任務按照嚴格的提交順序執行,在idk Executor的線程池中,多線程情況下可能無法保證提交的任務順序執行。
源碼分析
下面看下vertx的OrderedExecutor實現,其源碼并不長,如下:
private static final class OrderedExecutor implements Executor {
private final LinkedList<Runnable> tasks = new LinkedList<>();
private boolean running;
private final Executor parent;
private final Runnable runner;
public OrderedExecutor(Executor parent) {
this.parent = parent;
runner = () -> {
for (; ; ) {
final Runnable task;
synchronized (tasks) {
task = tasks.poll();
if (task == null) {
running = false;
return;
}
}
try {
task.run();
} catch (Throwable t) {
log.error("Caught unexpected Throwable", t);
}
}
};
}
public void execute(Runnable command) {
synchronized (tasks) {
tasks.add(command);
if (!running) {
running = true;
parent.execute(runner);
}
}
}
}
OrderedExecutor包含4個成員變量,tasks(LinkedList<Runnable>)是runnable隊列,parent(Executor)是真正執行runnable的執行器,runner(Runnable)是順序執行器要執行的任務,running為運行狀態標志。
首先分析runner,其運行的任務是個循環任務,只有當tasks中沒有要執行的任務了才退出。其邏輯很簡單,就是循環從tasks中獲取任務并執行。
再看execute方法,其邏輯也很簡單,就是向tasks中添加runnable,如果runner沒有執行,那么就將其提交給parent線程池運行起來。
因為runner是按順序從tasks中取任務執行的,因此保證了該OrderedExecutor execute的任務是按順序執行的。
再介紹下創建OrderedExecutor的工廠類OrderedExecutorFactory,其代碼如下:
public class OrderedExecutorFactory {
static final Logger log = LoggerFactory.getLogger(OrderedExecutorFactory.class);
private final Executor parent;
public OrderedExecutorFactory(Executor parent) {
this.parent = parent;
}
public OrderedExecutor getExecutor() {
return new OrderedExecutor(parent);
}
}
其代碼更簡單,就是傳入一個線程池執行器parent,每次創建OrderedExecutor要共享這個parent執行器。
下面分析下OrderedExecutor和Executor的關系,雖然OrderedExecutor實現了Executor,但它們并不是簡單的平行對等關系,1個Executor可以對應多個OrderedExecutor。
1個Executor相當于1個線程池,但每個OrderedExecutor在運行狀態會獨占1個線程,因為在把runner提交給parent執行時,parent會選出1個空閑線程執行該runner,而該runner是個循環任務,會獨占這個線程。
OrderedExecutor通過1個runner任務處理所有提交到該OrderedExecutor的runnable,當處理完tasks中所有任務后就把線程歸還給parent(Executor),當下次有新的runnable提交進來時再把runner提交給parent(Executor),parent再取出1個空閑線程運行runner,這個runner又獨占了這個線程。