1,com.xxx.mop.portal.web.listener.ThreadPoolListener是个监听器,他在容器启动时候的就实例化了一个ThreadPool,这个容器每隔60秒就启动一个业务定时同步线程。
2,com.xxx.mop.bfp.biz.sync.impl.BizSyncTaskPoller用来定时获取业务订购日志中,状态为-1(-1:未执行;0:正在执行:1:已经处理完毕)的订购进行重新处理。每次取出的条数是根据库中配置的“perFetchUnhandleLimit”参数来获取的。取出来未处理的日志后,转化成对应的订单(CorpOrder/UserOrder),将每个订单转化成一个业务同步任务(com.xxx.mop.bfp.biz.sync.impl.BizSyncTask),然后放入线程池中进行处理。
3,com.xxx.mop.bfp.biz.sync.impl.BizSyncTask的作用就是向业务系统同步任务,然后更新bialog的状态。
4,com.xxx.mop.commons.concurrent.ThreadPool自定义的线程池管理器,采用了ThreadPoolExecutor实现。
5,com.xxx.mop.commons.concurrent.TrackingExecutor自定义的线程池包装类。这个线程池可以获取在线程池关闭时未完成的任务清单。实际将未完成的任务添加到列表中返回是在com.xxx.mop.commons.concurrent.RunnableWrapper中完成的,当任务在执行时,如果发现线程池完毕或者当前的线程被终止,那么正在执行的任务就会加入未完成的任务队列(List<Runnable)中,然后在线程池最终关闭时将这些任务再写回数据库中。AbstractExecutorService在关闭时能够获取到从未执行的任务清单,但是不能获取到已经提交但是还没执行完毕(还没取消执行)的任务清单,因此这里设计了这个类,用户在线程池关闭时同时获取已经提交但是还未执行完毕的任务,然后取消这些任务(将任务的状态更新为-1,com.xxx.mop.bfp.biz.sync.impl.BizSyncTask中重写了reject()和cancel()方法),以备下次线程再次启动时重新执行这些任务。
6,注意java.util.Collections的用法。如Collections.emptyList()。
7,ThreadPool中关闭所有同步线程是通过添加一个“钩子”实现的。
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
logger.info("==shutdown all bizsync worker thread==");
shutdownAllThreadPool();
}
}));
上面的方法添加了一个钩子,当虚拟机关闭时就会启动这个线程,shutdownAllThreadPool()方法再将所有还没有完成的任务重新更新成初始状态。