有没有办法使用ExecutorService暂停/恢复特定线程?
private static ExecutorService threadpool = Executors.newFixedThreadPool(5);
想象一下,我想在id = 0时停止线程(假设为每个线程分配一个增量id,直到达到线程池的大小)。
过了一会儿,按一个按钮让我们说,我想恢复那个特定的线程,并让所有其他线程保持其当前状态,可以暂停或恢复。
我在Java文档中发现了一个未完成的PausableThreadPoolExecutor版本。但它不适合我需要的东西,因为它恢复了池中的所有线程。
如果没有办法使用ExecutorService的默认实现,那么任何人都可以指点我这个问题的Java实现吗?
谢谢!
答案 0 :(得分:7)
你走错了路。线程池拥有线程,并通过与代码共享它们可能会搞砸
您应该专注于使您的任务(传递给线程可取消/可中断),而不是直接与池拥有的线程交互。
另外,当你试图中断线程时,你不会知道正在执行什么工作,所以我不明白为什么你会对这样做感兴趣
<强>更新强>
取消在线程池中提交的任务的正确方法是通过Future
执行者返回的任务。
1)这样你就可以确定你试图取消你实际瞄准的任务了
2)如果你的任务已经设计为可以取消,那么你的任务就在那里
3)不要使用标志来表示取消,而是使用Thread.currentThread().interrupt()
代替
更新:
public class InterruptableTasks {
private static class InterruptableTask implements Runnable{
Object o = new Object();
private volatile boolean suspended = false;
public void suspend(){
suspended = true;
}
public void resume(){
suspended = false;
synchronized (o) {
o.notifyAll();
}
}
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
if(!suspended){
//Do work here
}
else{
//Has been suspended
try {
while(suspended){
synchronized(o){
o.wait();
}
}
}
catch (InterruptedException e) {
}
}
}
System.out.println("Cancelled");
}
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newCachedThreadPool();
InterruptableTask task = new InterruptableTask();
Map<Integer, InterruptableTask> tasks = new HashMap<Integer, InterruptableTask>();
tasks.put(1, task);
//add the tasks and their ids
Future<?> f = threadPool.submit(task);
TimeUnit.SECONDS.sleep(2);
InterruptableTask theTask = tasks.get(1);//get task by id
theTask.suspend();
TimeUnit.SECONDS.sleep(2);
theTask.resume();
TimeUnit.SECONDS.sleep(4);
threadPool.shutdownNow();
}
答案 1 :(得分:4)
建议:与您正在使用的标志相似/不同,为您需要暂停/取消暂停的每项任务创建一个semaphore,其中包含1个许可(new Semaphore(1)
)。在任务的工作周期开始时,输入如下代码:
semaphore.acquire();
semaphore.release();
这会导致任务获取信号量许可并立即释放它。现在,如果要暂停线程(例如,按下按钮),请从另一个线程调用semaphore.acquire()
。由于信号量现在有0个许可证,你的工作线程将在下一个周期开始时暂停,并等到你从另一个线程调用semaphore.release()
。
(acquire()
方法抛出InterruptedException
,如果你的工作线程在等待时被中断。还有另一种方法acquireUninterruptibly()
,它也试图获得许可,但是没有得到中断。)
答案 2 :(得分:-1)
一种情况可能是,一个人想模拟许多设备。设备具有功能。这些设备集合总共可以同时运行。现在,如果一个线程代表一个设备(或一个线程代表一个设备的功能),则可能要像start(), shutdown(), resume()