Java 为线程编写舒适的暂停/停止方法
对于Java中的一个线程子类,我试图编写一个方法Java 为线程编写舒适的暂停/停止方法,java,multithreading,java-threads,Java,Multithreading,Java Threads,对于Java中的一个线程子类,我试图编写一个方法checkPauseAndStop(),它的目的是作为一个好的线性函数,我可以在run()方法中定期调用它来检查是否有暂停/停止请求,并相应地采取行动 在完全正常的情况下,停止线程是通过InterruptedException来处理的,这会强制run()-代码处于try-catch状态,并且感觉容易出错(例如,thread.sleep()不再告诉您它可能抛出这样的异常) 有没有什么好方法可以在不妨碍run()方法的情况下在方法内部停止线程 代码示例
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();
如果您想捕获发送到线程的中断,执行清理,例如,您无法将整个run()代码块放在try/catch异常块中。原因是,如果您的线程正在执行任何类型的线程间信令,通过一个条件变量或eg的信号量(调用
wait()
方法),如果为线程设置了中断状态标志,则run()代码块将立即抛出一个InterruptedException
。但是,如果您想主动检查线程的中断状态,最简单的方法是喷洒一堆中断点,即checkPause()
方法,并将睡眠时间设置为几纳秒(如果设置了中断标志,则sleep()
方法将抛出InterruptedException)。这可以在不影响线程性能的情况下实现您的目标。请确保您尝试实现的目标真正有意义,并且不属于“让我们重新发明轮子”类别。制作任何通用的“一刀切”停止方法并不是一件小事,尽管对Java创建者来说也是如此。这就是为什么Thread.stop()方法被弃用的原因。()(Thread.destroy()实际上并没有在AICT中实现。)
这里有一个很好的解释:.我将使用一个
ScheduledExecutorService
(可以使用Executors.newSingleThreadScheduledExecutor
创建)和一个枚举运行状态{RUNNING,pause,STOPPED}
当状态正在运行时
,我们会继续调度延迟的任务(使用ScheduledExecutorService.schedule
)。每个任务都会检查是否仍在运行,,如果仍在运行,则将单个循环迭代排队(使用ExecutorService.submit
或Executor.execute
)。然后,它为下一次迭代安排一个新的延迟任务(与计时器不同,您可以使用它来代替,但代价是另一个线程)
如果状态为“暂停”
,我们将继续安排延迟的任务,以检查是否转换回“运行”
状态。但是我们没有为实际的循环迭代安排工作项
如果状态为“已停止”
,则我们停止调度任何更多延迟的任务
状态变量可以存储在一个简单的
volatile
字段中,该字段可以是静态的(如果只有其中一个),也可以封装在一个表示“线程”的对象中(实际上不再是单个线程,但从调用方的角度来看,它可以类似于一个线程)。一个简单的共享AtomicBoolean shouldStop
可能足以返回,而无需使用InterruptedException。无论采用哪种方式,您都必须决定循环中应将checkPauseRequest()
放置在何处。无论是1次还是多次,任何有意义的事情都能在某个单元工作后暂停/停止。考虑使用<代码>信号量< /代码>,而不是使用<代码>锁定< /代码>。原因就是,。当其他程序员看到一个锁时
,他们通常希望它用于互斥;但是当他们看到一个信号量时,他们希望它用于线程之间的信令。如果您使用锁
发送信号,可能会给其他程序员留下这样的印象,即您的编码风格“怪异”,而且可能不可信。@AndrewS我并没有真正理解您的论证。AtomicBoolean
除了作为Semaphore
的替代品之外,还有什么帮助呢?AtomicBoolean
是一个能够优雅地退出线程的例子,而不是捕获interruptedexception
并从捕获中返回Semaphonre
仍然可以暂停线程。@AndrewS我不知道,除了使用异常之外,我如何可以向后跳转多个作用域(除了为每个作用域调用run一次以退出)OP使用了“停止”这个词,但是t.stop()
做了一些与OP要求的非常不同的事情。在<代码> STORE()/SCOD>调用的接收端上的线程没有任何发言权:任何其他线程都可以随时调用<代码> THT()(或代码>),如果发生在一些重要的数据结构的中间,则没有线程<代码> t>代码>可以进行清理。另一方面,OP所要求的是线程t
在安全点检查它是否被要求暂停或停止的一种干净的方式。@besmirched,这就是为什么我包含了一个到教程的链接,描述如何使用中断。;-)虽然没有严格地提到这个问题,但我经常看到人们试图用Java实现“思想中的线程模型”,而不是使用Java中实际存在的线程模型。当然,我也在使用Java的monito实现信号量