Java ExecutorService暂停/恢复特定线程
有没有办法使用ExecutorService来暂停/恢复特定的线程?
private static ExecutorService threadpool = Executors.newFixedThreadPool(5);
想象一下,我想停止线程,因为id = 0(假设为每个线程分配一个增量id,直到达到线程池的大小)。
过了一会儿,按一个按钮让我们说,我想恢复那个特定的线程,并让所有其他线程保持其当前状态,可以暂停或恢复。
我在Java文档中找到了一个未完成的PausableThreadPoolExecutor版本。 但它不适合我需要的东西,因为它恢复了池中的所有线程。
如果没有办法使用ExecutorService的默认实现,那么任何人都可以指出我对这个问题的Java实现吗?
谢谢!
你走错了路。 线程池拥有线程,并通过与代码共享它们可能会搞砸。
您应该专注于使您的任务 (传递给线程可取消/可中断),而不是直接与池拥有的线程交互。
另外,当你试图中断线程时,你不会知道正在执行什么工作,所以我不明白为什么你会对这样做感兴趣
更新:
取消在线程池中提交的任务的正确方法是通过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 tasks = new HashMap(); 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个许可证的信号量 ( new Semaphore(1)
)。 在任务的工作周期开始时,输入如下代码:
semaphore.acquire(); semaphore.release();
这会导致任务获取信号量许可并立即释放它。 现在,如果你想暂停线程(例如按下一个按钮),从另一个线程调用semaphore.acquire()
。 由于信号量现在有0个许可,你的工作线程将在下一个周期的开始暂停,并等到你从另一个线程调用semaphore.release()
。
(如果你的工作线程在等待时被InterruptedException
,则acquire()
方法抛出InterruptedException
。还有另一种方法acquireUninterruptibly()
,它也试图获取许可,但不会被中断。)