如何实现线程池的暂停和恢复功能

来源:互联网 发布:零基础可能学大数据吗? 编辑:程序博客网 时间:2024/06/04 23:48

很多时候我们需要暂停线程池,而不是shutdown线程池,暂停线程池可以为我们保存任务,稍后可以继续执行,从而避免不必要的开销。

这里我提供一种暂停线程池的方法;

首先拿到ThreadPoolExecutor.java源码,将其变为自己包内的私有类;

接下来修改线程池,

先在线程池类中添加一下方法和变量:

BlockingQueue<Runnable> pauseQueue=new ArrayBlockingQueue<>(1);//暂停时用来则塞线程的空任务队列

isPause=true;//暂停

public void pause(){//暂停线程池,但是仍然接受任务        isPause=true;    System.out.println("暂停了"+isPause+exit);}public void resume(){//恢复线程池,开始接着执行任务    isPause=false;        if (workQueue.isEmpty()) {        return;    }    pauseQueue.offer(workQueue.poll());}
然后修改以下方法:

private Runnable getTask() {    boolean timedOut = false; // Did the last poll() time out?    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;        }        int wc = workerCountOf(c);        if (isPause){            try {                                return pauseQueue.take();            } catch (InterruptedException e) {                                           }                    }        // Are workers subject to culling?                boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;        if ((wc > maximumPoolSize || (timed && timedOut))                && (wc > 1 ||workQueue.isEmpty())) {            if (compareAndDecrementWorkerCount(c)) {                                return null;            }                        continue;        }        try {            Runnable r = timed ?// TODO: 2017/5/14 keepAliveTime为空闲线程存活的时间                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :// TODO: 2017/5/14 在空闲线程关闭之前尝试取走队列头的任务,如果还没有任务则返回null                    workQueue.take();// TODO: 2017/5/14 获取队列头的任务 然后 在从队列移除该任务;            if (r != null) {                                return r;            }            timedOut = true;// TODO: 2017/5/14 如果取不到任务则循环重取,如果队列已空则在上面返回空,当返回空时代表所有任务已完成,那么工作机器人会关闭并销毁                    } catch (InterruptedException retry) {            timedOut = false;                    }    }}
public void execute(Runnable command) {    if (command == null)        throw new NullPointerException();    
    if (isPause) {       if (!workQueue.offer(command))          reject(command);       return;    }
/* * Proceed in 3 steps: * * 1. If fewer than corePoolSize threads are running, try to * start a new thread with the given command as its first * task. The call to addWorker atomically checks runState and * workerCount, and so prevents false alarms that would add * threads when it shouldn't, by returning false. * * 2. If a task can be successfully queued, then we still need * to double-check whether we should have added a thread * (because existing ones died since last checking) or that * the pool shut down since entry into this method. So we * recheck state and if necessary roll back the enqueuing if * stopped, or start a new thread if there are none. * * 3. If we cannot queue task, then we try to add a new * thread. If it fails, we know we are shut down or saturated * and so reject the task. */ 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) == 0) addWorker(null, false); } else if (!addWorker( command, false)) reject(command);}
OK,先在只要调用pause()和resume()方法就能实现暂停和恢复。

源码下载

原创粉丝点击