对于Java中的Thread子类,我试图编写一个方法checkPauseAndStop()
,其目的是使单行代码更好,我可以在run()
方法中定期调用该方法以检查是否有暂停/停止请求并采取相应行动。
虽然功能齐全,但是通过InterruptedException
处理线程的停止,这迫使run()代码处于try-catch中,并且容易出错。
(例如Thread.sleep()不会再告诉您它可能会引发此类异常。
有没有什么好方法可以在方法内部处理停止线程而不会影响run()方法?
代码示例:
public class SuspendableThread extends Thread
{
private Semaphore lock = new Semaphore(1);
public void checkPauseRequest() throws InterruptedException
{
if (isInterrupted())
throw new InterruptedException();
lock.acquire();
lock.release();
}
@Override
public void run()
{
try
{
while (true)
{
// Do_stuff
checkPauseRequest();
}
}
catch (InterruptedException e)
{
return;
}
}
在这个特定示例中,根本没有必要。为了获得更大的效果,假设我们有50个或更多的连续块
// Do_stuff
checkPauseRequest();
而不是一个。
答案 0 :(得分:1)
如果要捕获发送给线程的中断,例如要执行清理,则无法避免将整个run()代码块放入try / catch异常块中。原因是,如果您的线程通过条件变量或信号量(例如,调用wait()
)执行任何类型的线程间信号传递,则run()代码块将立即抛出{{1 }},如果为线程设置了中断状态标志。但是,如果您要主动检查线程的中断状态,最简单的方法是喷洒一堆中断点,也就是您的InterruptedException
方法,并休眠几纳秒(您的如果设置了中断标志,则checkPause()
方法将引发InterruptedException。这样就可以实现您的目标,而不会过多地损害线程性能。
答案 1 :(得分:1)
我会使用ScheduledExecutorService
(可以用Executors.newSingleThreadScheduledExecutor
创建)和enum RunningState { RUNNING, PAUSED, STOPPED }
来构造它。
状态为RUNNING
时,我们将继续安排延迟的任务(使用ScheduledExecutorService.schedule
)。每个任务都会检查我们是否仍然RUNNING
,如果是,则排队一次循环迭代(使用ExecutorService.submit
或Executor.execute
)。然后,它为下一次迭代计划一个新的延迟任务(与Timer
一样,您可以潜在地使用它,但又会浪费另一个线程)。
如果状态为PAUSED
,我们将继续安排延迟的任务,以继续检查是否转换回RUNNING
状态。但是我们没有为实际的循环迭代安排工作项。
如果状态为STOPPED
,那么我们将停止安排其他任何延迟的任务。
状态变量可以存储在简单的volatile
字段中,该字段可以是静态的(如果只有这些东西之一)或可以包装在表示“线程”的对象中( '实际上不再是单个线程,但是从调用者的角度来看,它可以类似于一个线程。)
答案 2 :(得分:0)
请确保您要实现的目标确实有意义,并且不会属于让我们重新发明轮子类别。制作任何通用的“一刀切”停止方法并不是一件容易的事,尽管对于Java创建者来说也是如此。这就是不推荐使用Thread.stop()方法的原因。 (https://docs.oracle.com/javase/10/docs/api/java/lang/Thread.html#stop())(而且Thread.destroy()实际上并未实现AFAICT。)
有一个很好的解释:https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html。