JAVA并发编程之线程池ThreadPoolExcutor
在JAVA并发编程之线程池的最后我们讲到了创建定时线程池,其实线程池的创建仍旧是使用的ThreadPoolExcutor的构造函数,具体代码如下:
在我们了解ScheduledThreadPoolExecutor到底如何定时完成任务之前,先看下它的结构:
|
|
继承了ThreadPoolExecutor(参考JAVA并发编程之线程池)并实现了ScheduledExecutorService接口,
|
|
从上面的ScheduledExecutorService接口中我们可以知道定时任务的用法,下面我们我们具体看一下ScheduledThreadPoolExecutor中的实现:
|
|
从代码的实现中我们可以知道,传进来的Runnable或Callable接口接口的子类,将它们包装到ScheduledFutureTask中,然后把包装的ScheduledFutureTask放到线程池中执行。这里我们看一下ScheduledFutureTask的构造函数,它是ScheduledThreadPoolExecutor的内部类:
我们已经知道如何把Runnable包装成一个定时任务的,下面我们看一下这个任务是如何被延迟提交的
如果线程池没有关闭,检查当前线程池已启动的线程数,是否达到corePoolSize,没有的话,新建一个线程并启动它。注意,这个时候新建的线程是没有持有任何Runnable对象的,它是在启动后到queue(工作队列)中去取出任务执行。
任务的执行
在上面我们完成了任务的添加,在之前的文章中我们知道,任务的执行方法是调用的本身的run()方法,下面看一下
ScheduledFutureTask的run()
|
|
相信到这里你一定不会有恍然大悟的感觉,而是真是++了狗了,哪里有延迟的操作了,因此我们必须看一下DelayedWorkQueue中的任务是如何取出来的。
DelayedWorkQueue
这里主要是讲延迟操作任务,不会详细的讲解DelayedWorkQueue,在上面的分析中我们知道,worker的firstTask=null,因此任务要从队列中去取,下面我们看一下DelayedWorkQueue的take()方法:
|
|
这段代码我们就能明白任务是如何延迟执行的,我们取任务的时候会看一下任务的时间与当前时间的差值,如果小于0 证明任务已经到了执行的时间,任务取出执行,如果时间未到,则继续等待(等待和Condition有关,待学习)。