作为分布式定时任务框架,多线程调用必不可少,让我们看看有哪些地方用到了多线程的知识。
JobScheduleHelper类启动一个线程。把任务交给了JobTriggerPoolHelper类。JobTriggerPoolHelper类里面有两个线程池。fastTriggerPool和slowTriggerPool两个线程池。
线程池中调用XxlJobTrigger的trigger方法。在后续都基本上没有用到多线程异步调用。
以上是服务端的多线程调用情况,可以看到用到了线程池的技术。
让我们研究下线程池是如何使用的。
fastTriggerPool = new ThreadPoolExecutor(
10, // corePoolSize 核心线程数10个
XxlJobAdminConfig.getAdminConfig().getTriggerPoolFastMax(),//maximumPoolSize
最大200个线程。
60L, // keepAliveTime 线程存活时间,单位秒
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(1000), // 1000个数量大小的有界队列
new ThreadFactory() { // 如何创建线程
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode()); // 标注下线程的名字是fastTriggerPool
}
});
slowTriggerPool = new ThreadPoolExecutor(
10,// corePoolSize 核心线程数10个
XxlJobAdminConfig.getAdminConfig().getTriggerPoolSlowMax(),//maximumPoolSize
最大200个线程。
60L,//存活时间60秒。
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(2000),//2000个容量大小的有界队列
new ThreadFactory() { // 如何创建线程
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode());
}
});
执行器端如何利用线程异步执行任务?
EmbedServer启动服务接收服务。
当服务第一次启动时候,接收到调度端发送的调用job请求。
ExecutorBizImpl注册一个job对应的JobThread。并将该JobThread放入到
private static ConcurrentMap<Integer, JobThread> jobThreadRepository = new ConcurrentHashMap<Integer, JobThread>();
把线程放入到jobThreadRepository容器中。并启动线程。
同时调用JobThread的
public ReturnT<String> pushTriggerQueue(TriggerParam triggerParam) {...}方法。
将调度服务器发送的triggerParam转交给JobThread。JobThread则会按照指令执行任务。
生产者消费者模式
调度服务器相当于生产者生产任务。而JobThread则是消费者。将任务执行完并销毁,等待下一次任务执行指令。
triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);
poll()返回队首元素的同时删除队首元素,队列为空时返回NULL。
由这个api得知这是生产消费者模式。