Executor框架

Executor

ExecutorService

AbstractExecutorService

ThreadPoolExecutor

ThreadPoolExecutor继承AbstractExecutorService,是一个线程池的具体的实现

内部类 Worker

    private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable

代表线程池的一个工作线程,继承了AbstractQueuedSynchronizer,将该类实现为一个简单的互斥锁 。

重要的成员:

    final Thread thread;
Runnable firstTask;
volatile long completedTasks;

Worker封装了执行任务的线程,首次执行的任务,完成的任务数。

        Worker(Runnable firstTask) {
setState(-); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}

Worker初始化设置state为 -1(1表示锁被占用,0表示未被占用),因为 interruptIfStarted 方法中有 getState() >= 0,这样刚初始化还没运行task的线程不能被中断。

         void interruptIfStarted() {
Thread t;
if (getState() >= && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}

Worker.thread开始运行,执行 Worker 的run(),run()中调用 ThreadPoolExecutor 的 runWorker(this)

 final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}

这段代码是线程池实际执行task的代码,总结了几点说明一下:

1. 除 firstTask 外, 线程会不断的调用 getTask() 从 workQueue 中拉取任务执行;

2. task.run()前后执行 beforeExecute(wt, task); afterExecute(task, thrown)方法。这两个方法对自定义线程池功能扩展。

3. task.run()抛出的异常继续向上抛出。

4. task.run()执行时,序获得该Worker的锁。执行完成释放锁。

5. 第5行w.unlock(),设置Worker.state = 0,设置锁空闲状态,使其可以响应中断。其默认状态为 -1,不能响应中断。

6. 如果线程池停止,确认中断thread中断。处理shutDownNow竞争的问题,仔细阅读14-18行代码。

7. processWorkerExit(w, completedAbruptly) 处理Worker的退出。

getTask()的实现:

     private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out? retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c); // Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
} boolean timed; // Are workers subject to culling? for (;;) {
int wc = workerCountOf(c);
timed = allowCoreThreadTimeOut || wc > corePoolSize; if (wc <= maximumPoolSize && ! (timedOut && timed))
break;
if (compareAndDecrementWorkerCount(c))
return null;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
} try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}

getTask() 以blocking或者timed wait的方式从workQueue中拉取task,下面几种情况下返回null:

1. 线程池中线程数量多于maximumPoolSize时(因为调用了setMaximumPoolSize())

2. 线程池STOP

3. 线程池SHUTDOWN,workQueue为空

4. Worker等待任务超时,并且在等待之前和之后 Worker 是可 termination 的,即 (allowCoreThreadTimeOut || wc > corePoolSize)。

getTask()返回null时,completedAbruptly=false,runWorker()跳出while循环,执行processWorkerExit(),它的实现:

     private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);
} finally {
mainLock.unlock();
} tryTerminate(); int c = ctl.get();
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? : corePoolSize;
if (min == && ! workQueue.isEmpty())
min = ;
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null, false);
}
}

该方法主要由 Worker.thread调用,完成清理死亡的Worker和记录一些计量值。它从workers移除Worker、执行可能的terminate、替换Worker如果是因为用户task exeption导致该Wroker的退出,

或者当前线程池线程数小于corePoolSize。注意,除非completedAbruptly=true,不然workerCount已经在getTask()中被调整过了的(即已经减1了)。

内部类 CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy

几种不同的拒绝策略。

主要成员

    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;

AtomicInteger类型的私有变量ctl,使用高3bit表示线程池状态runState,低29bit来表示线程池线程总数。可见,Executor线程数量是有限制的,最多(2^29)-1个(about 500 million)。

前3bit表示线程池生命周期的5个状态,RNUNING,SHUTDOWN,STOP,TIDYING,TERMINATED。注释中给出了线程池所有可能的状态转化,随着生命周期的变更,几个状态从小到大赋值。

  • RUNNING 在ThreadPoolExecutor被实例化的时候就是这个状态
  • SHUTDOWN 通常是已经执行过shutdown()方法,不再接受新任务,等待线程池中和队列中任务完成
  • STOP 通常是已经执行过shutdownNow()方法,不接受新任务,队列中的任务也不再执行,并尝试终止线程池中的线程
  • TIDYING 线程池为空,就会到达这个状态,执行terminated()方法
  • TERMINATED terminated()执行完毕,就会到达这个状态,ThreadPoolExecutor终结
    private final BlockingQueue<Runnable> workQueue;

存储待执行tasks的任务队列。

    private final HashSet<Worker> workers = new HashSet<Worker>();

工作线程集合。

    private final ReentrantLock mainLock = new ReentrantLock();

访问workers时必须持有的锁。

    private final Condition termination = mainLock.newCondition();

mainLock Condition 用来支持 awaitTermination。

    private int largestPoolSize;

记录最大线程池大小,访问必须持有mainLock。

    private long completedTaskCount;

记录完成的任务数目,访问必须持有mainLock。

    private volatile ThreadFactory threadFactory;

volatile ThreadFactory 类变量,生产线程(addWorker方法)。用户可能会对线程总数有限制,在addWorker时可能导致失败。调用者必须有失败处理方案。

    private volatile RejectedExecutionHandler handler;

线程被线程池拒绝接收时调用。

    private volatile boolean allowCoreThreadTimeOut;

默认为false,core threads 保持永远激活状态。当为true时,核心线程等待keepAliveTime空闲时间后关闭。

    private volatile long keepAliveTime;

线程最多空闲等待的时间,之后自动关闭。

    private volatile int corePoolSize;

线程池最小存活的线程数目。当allowCoreThreadTimeOut为true时,该数目为0。

    private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();

默认的 rejected execution handler。

    private static final RuntimePermission shutdownPerm =
new RuntimePermission("modifyThread");

主要方法

前面介绍Worker的时候介绍了一些线程池的方法。下面接着介绍其主要的方法。最主要的execute()方法:

     public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == )
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}

提交新任务的时候,如果没达到核心线程数corePoolSize,则开辟新线程执行。如果达到核心线程数corePoolSize, 而队列未满,则放入队列,否则开新线程处理任务,直到maximumPoolSize,超出则丢弃处理。

代码中task加入workQueue前后都作了isRunning()的检查。也就是说,只有在加入队列后,线程池还保持RUNNING状态,才算加入workQueue成功。RejectedExecutionHandler处理丢弃的task,具体代码在reject(command)中。

shutdown()方法

     public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}

调用shutdown()方法,线程池至少处于SHUTDOWN状态。线程池不再接收新任务,之前提交的任务仍会执行。

shutdown()调用interruptIdleWorkers()方法,终止空闲的Workers:

     private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}

shutdownNow()方法和shutdown()方法差不多实现。

tryTerminate()方法是一个很重要的方法,在内部实现很多方法中,shutdown过程中,减少worker count或者从workQueue移除task后,需调用该方法。

     final void tryTerminate() {
for (;;) {
int c = ctl.get();
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
if (workerCountOf(c) != ) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
} final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, ))) {
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, ));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}

该方法实现的是,如果线程池(SHUTDOWN and pool and queue empty)或者(STOP and pool empty),将线程池状态转为TERMINATED。如果线程池(SHUTDOWN and pool not empty and queue empty)或者(STOP and pool not empty),执行interruptIdleWorkers(ONLY_ONE),中断一个idle worker确保shutdown信号传递(系统不再接受新的任务,不再产生新的Worker,workercount减少为0,Worker数量也减少到0)。其它情况直接返回。

awaitTermination(long timeout, TimeUnit unit)等待线程池终止。

     public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (;;) {
if (runStateAtLeast(ctl.get(), TERMINATED))
return true;
if (nanos <= )
return false;
nanos = termination.awaitNanos(nanos);
}
} finally {
mainLock.unlock();
}
}

purge()方法:

     public void purge() {
final BlockingQueue<Runnable> q = workQueue;
try {
Iterator<Runnable> it = q.iterator();
while (it.hasNext()) {
Runnable r = it.next();
if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
it.remove();
}
} catch (ConcurrentModificationException fallThrough) {
// Take slow path if we encounter interference during traversal.
// Make copy for traversal and call remove for cancelled entries.
// The slow path is more likely to be O(N*N).
for (Object r : q.toArray())
if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
q.remove(r);
} tryTerminate(); // In case SHUTDOWN and now empty
}

总结

ThreadPoolExecutor本身是个并发系统,关注作者编写并发程序的技巧(锁运用与竞争情况的考虑)。

ScheduledExecutorService

public interface ScheduledExecutorService extends ExecutorService

可以延迟固定时间或者定制执行时间执行task的ExecutorService。在ExecutorService基础上额外提供了4中方法的服务:

    public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);

ScheduledThreadPoolExecutor

内部类 ScheduledFutureTask

    private class ScheduledFutureTask<V>
extends FutureTask<V> implements RunnableScheduledFuture<V>

封装在SchedualedThreadPoolExector执行的task,继承FutrueTask,同时实现了Comparable和Delay接口。可以判断该task是否是repeating task,获取当前Delay,可与其它ScheduledFutureTask比较。

主要成员:

        //
private final long sequenceNumber;
private long time; 
//repeating task需要被re-enqueued
RunnableScheduledFuture<V> outerTask = this;
//period可判断是否是repeating task。正值fixed-rate,负值fixed-delay。0代表non-repeating task
private final long period;
int heapIndex;

run()方法重写了FutureTask的run()方法,是该task执行的主方法。重写是为当periodic = true时,周期性的执行task。执行非周期性task和周期性task分别使用FutureTask的run()和runAndReset()方法。

         public void run() {
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic))
cancel(false);
else if (!periodic)
ScheduledFutureTask.super.run();
else if (ScheduledFutureTask.super.runAndReset()) {
setNextRunTime();
reExecutePeriodic(outerTask);
}
}

canRunInCurrentRunState(periodic)判断能否在当前状态下运行,不能则调用cancel()方法:

        public boolean cancel(boolean mayInterruptIfRunning) {
boolean cancelled = super.cancel(mayInterruptIfRunning);
if (cancelled && removeOnCancel && heapIndex >= 0)
remove(this);
return cancelled;
}

内部类 DelayedWorkQueue

DelayedWorkQueue是JDK1.7以后内部实现的类,其实现了PriorityQueue和DelayQueue的功能,之前直接使用PriorityQueue。还是看看他的具体实现,顺便复习下集合的实现:

    static class DelayedWorkQueue extends AbstractQueue<Runnable>
implements BlockingQueue<Runnable> { /*
* A DelayedWorkQueue is based on a heap-based data structure
* like those in DelayQueue and PriorityQueue, except that
* every ScheduledFutureTask also records its index into the
* heap array. This eliminates the need to find a task upon
* cancellation, greatly speeding up removal (down from O(n)
* to O(log n)), and reducing garbage retention that would
* otherwise occur by waiting for the element to rise to top
* before clearing. But because the queue may also hold
* RunnableScheduledFutures that are not ScheduledFutureTasks,
* we are not guaranteed to have such indices available, in
* which case we fall back to linear search. (We expect that
* most tasks will not be decorated, and that the faster cases
* will be much more common.)
*
* All heap operations must record index changes -- mainly
* within siftUp and siftDown. Upon removal, a task's
* heapIndex is set to -1. Note that ScheduledFutureTasks can
* appear at most once in the queue (this need not be true for
* other kinds of tasks or work queues), so are uniquely
* identified by heapIndex.
*/ private static final int INITIAL_CAPACITY = 16;
private RunnableScheduledFuture[] queue =
new RunnableScheduledFuture[INITIAL_CAPACITY];
private final ReentrantLock lock = new ReentrantLock();
private int size = 0; /**
* Thread designated to wait for the task at the head of the
* queue. This variant of the Leader-Follower pattern
* (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to
* minimize unnecessary timed waiting. When a thread becomes
* the leader, it waits only for the next delay to elapse, but
* other threads await indefinitely. The leader thread must
* signal some other thread before returning from take() or
* poll(...), unless some other thread becomes leader in the
* interim. Whenever the head of the queue is replaced with a
* task with an earlier expiration time, the leader field is
* invalidated by being reset to null, and some waiting
* thread, but not necessarily the current leader, is
* signalled. So waiting threads must be prepared to acquire
* and lose leadership while waiting.
*/
private Thread leader = null; /**
* Condition signalled when a newer task becomes available at the
* head of the queue or a new thread may need to become leader.
*/
private final Condition available = lock.newCondition(); /**
* Set f's heapIndex if it is a ScheduledFutureTask.
*/
private void setIndex(RunnableScheduledFuture f, int idx) {
if (f instanceof ScheduledFutureTask)
((ScheduledFutureTask)f).heapIndex = idx;
} /**
* Sift element added at bottom up to its heap-ordered spot.
* Call only when holding lock.
*/
private void siftUp(int k, RunnableScheduledFuture key) {
while (k > 0) {
int parent = (k - 1) >>> 1;
RunnableScheduledFuture e = queue[parent];
if (key.compareTo(e) >= 0)
break;
queue[k] = e;
setIndex(e, k);
k = parent;
}
queue[k] = key;
setIndex(key, k);
} /**
* Sift element added at top down to its heap-ordered spot.
* Call only when holding lock.
*/
private void siftDown(int k, RunnableScheduledFuture key) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
RunnableScheduledFuture c = queue[child];
int right = child + 1;
if (right < size && c.compareTo(queue[right]) > 0)
c = queue[child = right];
if (key.compareTo(c) <= 0)
break;
queue[k] = c;
setIndex(c, k);
k = child;
}
queue[k] = key;
setIndex(key, k);
} /**
* Resize the heap array. Call only when holding lock.
*/
private void grow() {
int oldCapacity = queue.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%
if (newCapacity < 0) // overflow
newCapacity = Integer.MAX_VALUE;
queue = Arrays.copyOf(queue, newCapacity);
} /**
* Find index of given object, or -1 if absent
*/
private int indexOf(Object x) {
if (x != null) {
if (x instanceof ScheduledFutureTask) {
int i = ((ScheduledFutureTask) x).heapIndex;
// Sanity check; x could conceivably be a
// ScheduledFutureTask from some other pool.
if (i >= 0 && i < size && queue[i] == x)
return i;
} else {
for (int i = 0; i < size; i++)
if (x.equals(queue[i]))
return i;
}
}
return -1;
} public boolean contains(Object x) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return indexOf(x) != -1;
} finally {
lock.unlock();
}
} public boolean remove(Object x) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = indexOf(x);
if (i < 0)
return false; setIndex(queue[i], -1);
int s = --size;
RunnableScheduledFuture replacement = queue[s];
queue[s] = null;
if (s != i) {
siftDown(i, replacement);
if (queue[i] == replacement)
siftUp(i, replacement);
}
return true;
} finally {
lock.unlock();
}
} public int size() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return size;
} finally {
lock.unlock();
}
} public boolean isEmpty() {
return size() == 0;
} public int remainingCapacity() {
return Integer.MAX_VALUE;
} public RunnableScheduledFuture peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return queue[0];
} finally {
lock.unlock();
}
} public boolean offer(Runnable x) {
if (x == null)
throw new NullPointerException();
RunnableScheduledFuture e = (RunnableScheduledFuture)x;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = size;
if (i >= queue.length)
grow();
size = i + 1;
if (i == 0) {
queue[0] = e;
setIndex(e, 0);
} else {
siftUp(i, e);
}
if (queue[0] == e) {
leader = null;
available.signal();
}
} finally {
lock.unlock();
}
return true;
} public void put(Runnable e) {
offer(e);
} public boolean add(Runnable e) {
return offer(e);
} public boolean offer(Runnable e, long timeout, TimeUnit unit) {
return offer(e);
} /**
* Performs common bookkeeping for poll and take: Replaces
* first element with last and sifts it down. Call only when
* holding lock.
* @param f the task to remove and return
*/
private RunnableScheduledFuture finishPoll(RunnableScheduledFuture f) {
int s = --size;
RunnableScheduledFuture x = queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
setIndex(f, -1);
return f;
} public RunnableScheduledFuture poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
RunnableScheduledFuture first = queue[0];
if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
return null;
else
return finishPoll(first);
} finally {
lock.unlock();
}
} public RunnableScheduledFuture take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture first = queue[0];
if (first == null)
available.await();
else {
long delay = first.getDelay(TimeUnit.NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
else if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
} public RunnableScheduledFuture poll(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture first = queue[0];
if (first == null) {
if (nanos <= 0)
return null;
else
nanos = available.awaitNanos(nanos);
} else {
long delay = first.getDelay(TimeUnit.NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
if (nanos <= 0)
return null;
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
long timeLeft = available.awaitNanos(delay);
nanos -= delay - timeLeft;
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
} public void clear() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
for (int i = 0; i < size; i++) {
RunnableScheduledFuture t = queue[i];
if (t != null) {
queue[i] = null;
setIndex(t, -1);
}
}
size = 0;
} finally {
lock.unlock();
}
} /**
* Return and remove first element only if it is expired.
* Used only by drainTo. Call only when holding lock.
*/
private RunnableScheduledFuture pollExpired() {
RunnableScheduledFuture first = queue[0];
if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
return null;
return finishPoll(first);
} public int drainTo(Collection<? super Runnable> c) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
RunnableScheduledFuture first;
int n = 0;
while ((first = pollExpired()) != null) {
c.add(first);
++n;
}
return n;
} finally {
lock.unlock();
}
} public int drainTo(Collection<? super Runnable> c, int maxElements) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
final ReentrantLock lock = this.lock;
lock.lock();
try {
RunnableScheduledFuture first;
int n = 0;
while (n < maxElements && (first = pollExpired()) != null) {
c.add(first);
++n;
}
return n;
} finally {
lock.unlock();
}
} public Object[] toArray() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return Arrays.copyOf(queue, size, Object[].class);
} finally {
lock.unlock();
}
} @SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (a.length < size)
return (T[]) Arrays.copyOf(queue, size, a.getClass());
System.arraycopy(queue, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
} finally {
lock.unlock();
}
} public Iterator<Runnable> iterator() {
return new Itr(Arrays.copyOf(queue, size));
} /**
* Snapshot iterator that works off copy of underlying q array.
*/
private class Itr implements Iterator<Runnable> {
final RunnableScheduledFuture[] array;
int cursor = 0; // index of next element to return
int lastRet = -1; // index of last element, or -1 if no such Itr(RunnableScheduledFuture[] array) {
this.array = array;
} public boolean hasNext() {
return cursor < array.length;
} public Runnable next() {
if (cursor >= array.length)
throw new NoSuchElementException();
lastRet = cursor;
return array[cursor++];
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
DelayedWorkQueue.this.remove(array[lastRet]);
lastRet = -1;
}
}
}

可以看到DelayedWorkQueue基本上就是实现了基于堆的优先级队列,take()、poll()函数实现为DelayQueue的延迟获取。他增加了两点服务,1.为堆中的每个元素RunnableScheduledFuture对象,增加了其在堆中的索引的字段。2.应用了leader-follower模式来最小化并发取元素的等待时间。leader线程在Delay时间后一定会被唤醒,去获取queue[0],take()或poll()成功后,释放leader权,其它等待的线程竞争leader权。每当一个新的RunnableScheduledFuture对象成为queue[0]时,执行leader=null, available.signal()设置leader为空,释放lock Condition。如果此时有新的线程取竞争获取queue[0],它就会成为leader,由它来释放Condition,否则还是有原来的leader线程释放Condition。

主要成员

//False if should cancel/suppress periodic tasks on shutdown
private volatile boolean continueExistingPeriodicTasksAfterShutdown;
//False if should cancel non-periodic tasks on shutdown.
private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
//True if ScheduledFutureTask.cancel should remove from queue
private volatile boolean removeOnCancel = false;
//Sequence number to break scheduling ties, and in turn to guarantee FIFO order among tied entries.
private static final AtomicLong sequencer = new AtomicLong();

主要方法

ScheduledThreadPoolExecutor对提交的任务制定了不同的执行方法,通过schedule()方法来执行:

    public <T> Future<T> submit(Callable<T> task) {
return schedule(task, 0, TimeUnit.NANOSECONDS);
} public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay,
TimeUnit unit) {
if (callable == null || unit == null)
throw new NullPointerException();
RunnableScheduledFuture<V> t = decorateTask(callable,
new ScheduledFutureTask<V>(callable,
triggerTime(delay, unit)));
delayedExecute(t);
return t;
}

他首先调用decorateTask()方法将callable封装成RunnableScheduledFuture,然后调用delayedExecute()执行。

    protected <V> RunnableScheduledFuture<V> decorateTask(
Callable<V> callable, RunnableScheduledFuture<V> task) {
return task;
} private void delayedExecute(RunnableScheduledFuture<?> task) {
if (isShutdown())
reject(task);
else {
super.getQueue().add(task);
if (isShutdown() &&
!canRunInCurrentRunState(task.isPeriodic()) &&
remove(task))
task.cancel(false);
else
ensurePrestart();
}
}

delayedExecute(task)在可执行的情况下将task放入workQueue中。

Executors

总结

JDK线程池框架Executor源码阅读的更多相关文章

  1. 线程池:ThreadPoolExcutor源码阅读

    ThreadPoolExcutor源码流程图:(图片较大,下载再看比较方便) 线程池里的二进制奥秘 前言: 线程池的五种状态state(RUNNING.SHUTDOWN.STOP.TIDYING.TE ...

  2. 如何查看JDK以及JAVA框架的源码

    如何查看JDK以及JAVA框架的源码 设置步骤如下: 1.点 “window”-> "Preferences" -> "Java" -> &q ...

  3. 如何阅读jdk及开源框架的源码?

    1.熟悉设计模式 可以边读源码 ,边熟悉设计模式,理解编程思想. jdk中对应的设计模式见:http://blog.csdn.net/gtuu0123/article/details/6114197 ...

  4. JUC(4)---java线程池原理及源码分析

    线程池,既然是个池子里面肯定就装很多线程. 如果并发的请求数量非常多,但每个线程执行的时间很短,这样就会频繁的创建和销毁 线程,如此一来会大大降低系统的效率.可能出现服务器在为每个请求创建新线程和销毁 ...

  5. 线程池:ThreadPoolExecutor源码解读

    目录 1 带着问题去阅读 1.1 线程池的线程复用原理 1.2 线程池如何管理线程 1.3 线程池配置的重要参数 1.4 shutdown()和shutdownNow()区别 1.5 线程池中的两个锁 ...

  6. Java并发—线程池框架Executor总结(转载)

    为什么引入Executor线程池框架 new Thread()的缺点 每次new Thread()耗费性能 调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞 ...

  7. Java线程池ThreadPoolExector的源码分析

    前言:线程是我们在学习java过程中非常重要的也是绕不开的一个知识点,它的重要程度可以说是java的核心之一,线程具有不可轻视的作用,对于我们提高程序的运行效率.压榨CPU处理能力.多条线路同时运行等 ...

  8. Java线程池及其底层源码实现分析

    1.相关类 Executors  ExecutorService   Callable   ThreadPool     Future 2.相关接口 Executor Executor接口的使用: p ...

  9. Java ThreadPoolExecutor线程池原理及源码分析

    一.源码分析(基于JDK1.6) ThreadExecutorPool是使用最多的线程池组件,了解它的原始资料最好是从从设计者(Doug Lea)的口中知道它的来龙去脉.在Jdk1.6中,Thread ...

随机推荐

  1. 【数论】P1029 最大公约数和最小公倍数问题

    题目链接 P1029 最大公约数和最小公倍数问题 思路 如果有两个数a和b,他们的gcd(a,b)和lcm(a,b)的乘积就等于ab. 也就是: ab=gcd(a,b)*lcm(a,b) 那么,接下来 ...

  2. CF1163E Magical Permutation【线性基,构造】

    题目描述:输入一个大小为\(n\)的正整数集合\(S\),求最大的\(x\),使得能构造一个\(0\)到\(2^x-1\)的排列\(p\),满足\(p_i\oplus p_{i+1}\in S\) 数 ...

  3. word 插入表格,位置不在最左边

    首先想到的是 样式的问题.

  4. [CTF]抓住那只猫(XCTF 4th-WHCTF-2017)

    原作者:darkless 题目描述:抓住那只猫 思路: 打开页面,有个输入框输入域名,输入baidu.com进行测试 发现无任何回显,输入127.0.0.1进行测试. 发现已经执行成功,执行的是一个p ...

  5. 网络IPC:套接字接口概述

    网络IPC:套接字接口概述 套接字接口实现了通过网络连接的不同计算机之间的进程相互通信的机制. 套接字描述符(创建套接字) 套接字是通信端点的抽象,为创建套接字,调用socket函数 #include ...

  6. Python多线程与多进程详解

    进程,线程,协程https://blog.csdn.net/qq_23926575/article/details/76375337 多进程 https://www.cnblogs.com/lipij ...

  7. PostgreSQL学习笔记(九) 用户、角色、权限管理

    PostgreSQL是一个多用户数据库,可以为不同用户指定允许的权限. 角色PostgreSQL使用角色的概念管理数据库访问权限. 根据角色自身的设置不同,一个角色可以看做是一个数据库用户,或者一组数 ...

  8. 文献阅读 | Molecular Architecture of the Mouse Nervous System

    文章亮点: 按level来管理和分析数据,文章有不同stage,每个stage有不同subtype,这应该是一个真tree,而不只是一个进化树,文章里出现最多的进化树把所有的stage都整合了. 空间 ...

  9. 阿里druid连接池监控数据自定义存储

    如何将druid连接池监控到的sql执行效率,连接池资源情况等进行持久化存储,方便系统运维分析优化,以下案例初步测试成功. 第一部: 新建MyDruidStatLogger类实现接口 extends ...

  10. radioButon的使用

    界面: <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android=& ...