1 类的继承关系
2 代码详情
SingleThreadEventExecutor
类签名
public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor
是一个抽象类
继承自AbstractScheduledEventExecutor
实现了OrderedEventExecutor接口,OrderedEventExecutor接口没有任何的方法,它是是一个标记性质的接口,表示的一个串行的EventExecutor
顾名思义它是单线程的
字段
private final Queue taskQueue;任务队列
private volatile Thread thread;线程
private volatile ThreadProperties threadProperties;线程属性
private final Executor executor;jdk中的接口
private volatile boolean interrupted;
private final CountDownLatch threadLock = new CountDownLatch(1);
private final Set shutdownHooks = new LinkedHashSet();
private final boolean addTaskWakesUp;
private final int maxPendingTasks;
private final RejectedExecutionHandler rejectedExecutionHandler;
private long lastExecutionTime;
private volatile int state = ST_NOT_STARTED;
- SingleThreadEventExecutor总共有一下这几种状态
-
还没有启动private static final int ST_NOT_STARTED = 1; - 已经启动: private static final int ST_STARTED = 2;
- 正在关闭: private static final int ST_SHUTTING_DOWN = 3;
- 已经关闭: private static final int ST_SHUTDOWN = 4;
- 已终止: private static final int ST_TERMINATED = 5;
private volatile long gracefulShutdownQuietPeriod;
private volatile long gracefulShutdownTimeout;
private long gracefulShutdownStartTime;
private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
构造函数:protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,boolean addTaskWakesUp, int maxPendingTasks,RejectedExecutionHandler rejectedHandler)
参数
-
EventExecutorGroup parent:用于给父类AbstractEventExecutor#parent赋值
-
Executor executor,会对这个Executor进行装饰使得在提交给executor执行的Runnable中,调用ThreadExecutorMap.currentExecutor返回的是this 这个eventExecutor
- this.executor = ThreadExecutorMap.apply(executor, this);
-
boolean addTaskWakesUp给this.addTaskWakesUp赋值,为true,则addTask(Runnable)会唤醒执行器线程
-
int maxPendingTasks,给this.maxPendingTasks赋值,但是最小值16,表示任务被拒绝前最多可以挂起多少任务
-
RejectedExecutionHandler rejectedHandler,拒绝策略
new一个长度为this.maxPendingTasks的LinkedBlockingQueue然后给 this.taskQueue赋值
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,boolean addTaskWakesUp, Queue taskQueue,RejectedExecutionHandler rejectedHandler)
参数
-
EventExecutorGroup parent:用于给父类AbstractEventExecutor#parent赋值
-
Executor executor,会对这个Executor进行装饰使得在提交给executor执行的Runnable中,调用ThreadExecutorMap.currentExecutor返回的是this 这个eventExecutor
- this.executor = ThreadExecutorMap.apply(executor, this);
-
boolean addTaskWakesUp给this.addTaskWakesUp赋值,为true,则addTask(Runnable)会唤醒执行器线程
-
taskQueue给this.taskQueue赋值
-
RejectedExecutionHandler rejectedHandler,拒绝策略
this.maxPendingTasks=Integer的最大值或者依赖于系统变量
public boolean inEventLoop(Thread thread)
return thread == this.thread;
判断这个线程是否在eventLoop中,如果它和SingleThreadEventExecutor中的this.thread是一个对象则是在eventLoop中
public void execute(Runnable task)
SingleThreadEventExecutor对jdk中的这个接口的实现
调用私有方法 private void execute(Runnable task, boolean immediate),其中执行!(task instanceof LazyRunnable) && wakesUpForTask(task)去判断是否需要立即执行immediate
目前wakesUpForTask是直接return true
private void execute(Runnable task, boolean immediate)
判断当前线程是否在eventloop中
-
boolean inEventLoop = inEventLoop();
加入到任务队列this.taskQueue中:addTask(task);
如果当前线程在eventloop中则,如果addTaskWakesUp为false,且immediate=true则调用 wakeup(inEventLoop);唤醒
不在eventloop中则
- 启动线程: startThread();
- 如果SingleThreadEventExecutor已经关闭:isShutdown()则执行一下操作:
- 在任务队列中删除该任务:removeTask(task)
- 删除成功则执行reject();该方法会抛jdk中的异常:RejectedExecutionException
protected void addTask(Runnable task)
执行offerTask(task),如果return false则执行reject(task);
final boolean offerTask(Runnable task)
如果已经关闭:isShutdown()=true,则执行reject();否则调用taskQueue.offer(task);
protected static void reject()
throw new RejectedExecutionException("event executor terminated");
public boolean isShutdown()
return state >= ST_SHUTDOWN;
state >= 关闭
private void startThread()
1 将this.state的状态由ST_NOT_STARTED通过cas变成ST_STARTED
2 真正启动线程doStartThread();
3 如果启动线程失败则,通过cas在把this.state 由ST_STARTED改成ST_NOT_STARTED
private void doStartThread()
核心代码
断言this.thread == null,这个变量是用于存储执行eventloop的线程的
向this.executor提交一个Runnable,于是executor中的一个线程会执行这个Runnable
-
获取当前的线程给this.thread赋值,于是this.thread就存储了执行eventloop的线程了
-
如果this.interrupted = true, 则打断线程thread.interrupt();
-
更新最后一次执行任务的时间戳this.lastExecutionTime
-
调用SingleThreadEventExecutor.this.run();去执行#taskQueue中的任务,这个方法在SingleThreadEventExecutor中抽象方法
-
finally中执行
-
进入一个无限循环中,直到this.state被通过cas改成了ST_SHUTTING_DOWN
-
无限调用confirmShutdown(),直到这个方法返回true
-
进入一个无限循环中,直到this.state被通过cas改成了ST_SHUTDOWN
-
再一次调用 confirmShutdown();
-
在finally中执行
-
cleanup();这个方法是抽象方法
-
finally语句中执行
-
FastThreadLocal.removeAll(); https://github.com/netty/netty/issues/6596. - 将this.state改成ST_TERMINATED
-
private final CountDownLatch threadLock = new CountDownLatch(1);对这个变量执行: threadLock.countDown(); - 抽干任务队列drainTasks();,如果还有任务的话,则需要打日志
- 对变量 private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);调用 terminationFuture.setSuccess(null);
-
-
-
protected boolean confirmShutdown()
确定是否可以关闭
1 判断是否正在关闭isShuttingDown():state >= ST_SHUTTING_DOWN;
2 必须在eventloop中否则抛出异常:throw new IllegalStateException("must be invoked from an event loop");
3 取消所有的定时任务,并清空优先级队列: AbstractScheduledEventExecutor#cancelScheduledTasks();
4 记录下this.gracefulShutdownStartTime
5 跑所有的任务,包括SingleThreadEventExecutor#Queue taskQueue;和父类中的优先级队列中的定时任务
- 1 将父类AbstractScheduledEventExecutor中优先级队列中的ScheduledFutureTask删掉,然后投入SingleThreadEventExecutor#Queue taskQueue;中
- 2 遍历taskQueue所有的Runnable,依次执行
- 3 调用钩子方法 afterRunningAllTasks();它在SingleThreadEventExecutor中是空实现的
6 如果5中没有任务了,那么则跑所有的shutdown 钩子: private final Set shutdownHooks,跑完之后,清空shutdownHooks
7 有任务跑,或者有钩子跑的话 ,那么就返回
- 如果已经关闭,则return true
- 如果gracefulShutdownQuietPeriod=0, 则返回true
- 否则:taskQueue.offer(WAKEUP_TASK); return false;
8 当前没有任务了,钩子也跑过了则
-
如果已经关闭,则return true
-
当前时间-关闭起始时间this.gracefulShutdownStartTime > 关闭超时时长gracefulShutdownTimeout,则return true
-
if (nanoTime - lastExecutionTime <= gracefulShutdownQuietPeriod)
- taskQueue.offer(WAKEUP_TASK);
- Thread.sleep(100);
- return false;
-
否则:return true
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit)
语义:要等过了quietPeriod这么多时间都没有任务提交的话,才会关闭,但是如果过了timeout,就会强行关闭
1 检验
-
quietPeriod必须大于等于0:ObjectUtil.checkPositiveOrZero(quietPeriod, "quietPeriod"); - if (timeout < quietPeriod) ,则抛异常
- ObjectUtil.checkNotNull(unit, "unit");
3 如果状态是>=ST_SHUTTING_DOWN,返回terminationFuture
4 进入一下无限循环里面执行一下代码
-
如果状态是>=ST_SHUTTING_DOWN,返回terminationFuture
-
计算新的状态
- 如果当前线程在eventloop中则新状态是ST_SHUTTING_DOWN
- 如果当前线程不在eventloop中,则如果当前状态是ST_NOT_STARTED后者ST_STARTED的话,则新状态是ST_SHUTTING_DOWN,否则新状态等于老状态
-
用cas将this.state改成新状态,cas成功则跳出循环
5 确保线程启动:ensureThreadStarted(oldState),如果启动失败则返回terminationFuture
6 如果线程启动成功,如果在eventloop中,或者不在eventloop中,但是此时已经进入关闭流程了,则执行
- taskQueue.offer(WAKEUP_TASK);
- if (!addTaskWakesUp) { wakeup(inEventLoop); }
7 return terminationFuture
public boolean awaitTermination(long timeout, TimeUnit unit)
1 检验
- ObjectUtil.checkNotNull(unit, "unit");
- if (inEventLoop()) { throw new IllegalStateException("cannot await termination of the current thread"); }
2 threadLock.await(timeout, unit);
- private final CountDownLatch threadLock = new CountDownLatch(1);