公司预计要成立派单组,成立之初已经预估了HC,即不管多少活,就这些人力,不管你手头有没有活,来新活就轮询安排,领导偶尔想找个人单独部署点活儿,轮到你了,算你'幸运',原来的活还要干,新安排的活儿是白加的小菜,所有的活还是按照正常的调度来完成,领导新加的小菜也不例外(不加塞)。
ParallelScheduler的实现和ElasticScheduler非常类似,底层都是使用单线程的ScheduledThreadPoolExecutor来调度任务,不同的是ElasticScheduler下面的员工人数(ScheduledThreadPoolExecutor),是自适配的,即任务少时,甚至可以全部解雇来释放资源,并发任务多时,可以无限制招聘新雇员,当然在极端情况下内存是存在隐患的。ParallelScheduler则在创建时就已经固定了员工数(ScheduledThreadPoolExecutor)。使用ParallelScheduler时,当任务数远超员人数时,很容易导致任务的阻塞。
ParallelScheduler核心代码
//new ParallelScheduler时,就已经初始化executors了
volatile ScheduledExecutorService[] executors;
ParallelScheduler(int n, ThreadFactory factory) {
if (n <= 0) {
throw new IllegalArgumentException("n > 0 required but it was " + n);
}
this.n = n;
this.factory = factory;
init(n);
}
void init(int n) {
ScheduledExecutorService[] a = new ScheduledExecutorService[n];
for (int i = 0; i < n; i++) {
a[i] = Schedulers.decorateExecutorService(this, this.get());
}
EXECUTORS.lazySet(this, a);
}
//抽调人员时使用轮询的方式
ScheduledExecutorService pick() {
ScheduledExecutorService[] a = executors;
if (a != SHUTDOWN) {
// ignoring the race condition here, its already random who gets which executor
int idx = roundRobin;
if (idx == n) {
idx = 0;
roundRobin = 1;
} else {
roundRobin = idx + 1;
}
return a[idx];
}
return TERMINATED;
}
最后再次总结两点
1. ElasticScheduler高并发时,可以无限制扩容,生产线程(每个ScheduledThreadPoolExecutor对应一个线程),存在内存溢出风险
2. ParallelScheduler线程数(ScheduledThreadPoolExecutor)固定,高并发时可能存在延迟问题