为线程编写一个舒适的暂停/停止方法



对于Java中的线程子类,我试图编写一个方法checkPauseAndStop(),其目的是成为很好的单行,我可以在run()方法中定期调用以检查是否有暂停/停止请求并采取相应的行动。

虽然功能齐全,但停止线程是通过InterruptedException处理的,这会强制 run((-code 处于 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();

而不仅仅是一个。

我会使用ScheduledExecutorService(您可以使用Executors.newSingleThreadScheduledExecutor创建(和enum RunningState { RUNNING, PAUSED, STOPPED }来构建它。

当状态为RUNNING时,我们不断调度延迟的任务(使用ScheduledExecutorService.schedule(。每个任务检查我们是否仍在RUNNING,如果是,则对单个循环迭代进行排队(使用ExecutorService.submitExecutor.execute(。然后它为下一次迭代安排一个新的延迟任务(与Timer不同,您可能会使用它,但代价是另一个线程(。

如果状态为PAUSED,我们会继续安排延迟的任务,以继续检查是否转换回RUNNING状态。但是,我们不会为实际循环迭代计划工作项。

如果状态为STOPPED,则我们停止计划任何更多延迟的任务。

state 变量可以存储在一个简单的volatile字段中,该字段可以是静态的(如果只有这些东西中的一个(,也可以包装在表示"线程"的对象中(实际上不再是单个线程,但从调用者的角度来看可以类似于一个线程(。

如果你想捕获发送到线程的中断,执行清理,例如,你不能绕过将整个 run(( 代码块放在 try/catch 异常块中。原因是,如果您的线程正在通过条件变量或信号量执行任何类型的线程间信号,例如(调用wait()方法(,如果您的 run(( 代码块将立即抛出一个InterruptedException,如果为线程设置了中断状态标志。但是,如果要主动检查线程的中断状态,最简单的方法是喷洒一堆中断点,也就是checkPause()方法,并休眠几纳秒(如果设置了中断标志,则sleep()方法将引发 InterruptedException(。这样可以实现您的目标,而不会对线程性能造成太大影响。

请确保您要实现的目标确实有意义,并且不属于让我们重新发明轮子类别。制作任何通用的一刀切停止方法都不是一件小事,尽管它看起来甚至对 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。

最新更新