【发布时间】:2018-09-05 18:47:50
【问题描述】:
对于 Java 中的 Thread 子类,我正在尝试编写一个方法 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();
而不仅仅是一个。
【问题讨论】:
-
lock需要被其他线程访问,这样它才能acquire(),所以当它acquire()s 时,这个线程会暂停。一个简单的 sharedAtomicBoolean shouldStop可能足以返回而无需使用 InterruptedException。无论哪种方式,您仍然必须决定checkPauseRequest()应该放在循环中的哪个位置。无论是 1 次还是多次,都可以在某个工作单元之后暂停/停止。 -
考虑使用
Semaphore而不是Lock。原因是,principle of least astonishment。当其他程序员看到Lock时,他们通常希望它用于互斥;但是当他们看到Semaphore时,他们希望它用于线程之间的信号传递。如果您使用Lock发出信号,可能会给其他程序员留下您的编码风格“怪异”的印象,并且可能不值得信赖。 -
@AndrewS 我并没有真正遵循您的论点。除了作为
Semaphore的替代品之外,AtomicBoolean在这里有何帮助? -
AtomicBoolean是一个能够优雅地退出线程的示例,而不是捕获InterreuptedException并从捕获中返回。Semaphonre仍然可以暂停线程。 -
@AndrewS 但是,我没有看到,除了使用异常之外,我还可以向后跳转多个作用域(除了为每个作用域调用 run 一次以退出)
标签: java multithreading java-threads