我有一个带有run方法的Java
线程来计算很多东西。您可以将其视为一系列数学语句,如下所示。请注意,每个计算可能会使用其他方法,而这些方法又可能具有其他循环等。
public void run() {
[computation 1 goes here here that takes a few seconds]
[computation 2 goes here that takes a few seconds]
....
[computation 30 goes here that takes a few seconds]
}
有GUI
打印这些语句的输出,因为它们会产生结果,我希望用户能够随时说“停止”。这是我想到的两种方法
方法1:许多布尔检查[LOOKS TERRIBLE]
private boolean stop;
public void run() {
if(!stop)
[computation 1 goes here here that takes a few seconds]
if(!stop)
[computation 2 goes here that takes a few seconds]
....
if(!stop)
[computation 30 goes here that takes a few seconds]
}
在此方法中,一旦stop标志设置为true,计算将结束。注意这看起来多么愚蠢,有30个if
语句。重要的是,这里的关键问题是如何经常提出这些条件。请注意,每行上的计算不一定是单行。极端情况下,run()
方法中的每一行都应该在它之上进行if(!stop)
调用吗?这似乎不是一个好的设计。
方法2:推广计算[不能这样做]
pirivate boolean stop;
public void run() {
for(int i = 0; i < computationsN && !stop; i++) {
computuations.get(i).compute();
}
我想这个方法会被提出来,所以我想简单地声明在我的情况下这是不可能的,因为线条的纯粹变化我称之为“计算”以简化。我通常对基本while
循环的线程执行此操作,并且它适用于此类。但是在这种情况下,run()
方法只是变量代码的一种巨大方法。
还有其他解决方案吗?这似乎应该是一个普遍的问题。提前谢谢!
答案 0 :(得分:5)
你想要做的事情实际上可以通过方法2完成,但你必须使用Strategy Pattern,这真的是你需要的一件事,因为它可以在一行中简化你的计算就像你在方法2中所做的一样。
它的工作方式如下,它允许您通过执行多态来更改下一个可执行算法。
首先,您必须在不同的类中制作所有算法,并且每个算法都必须使用一种方法(即Computable
方法)实现一个接口(可以称为compute()
)。
实施例
public interface Computable {
public void compute();
}
您的算法类可能类似于:
public class AlgorithmX implements Computable {
@Override
public void compute() {
// TODO Your Real Computation here for the Algorithm X
}
}
然后在for
循环中,您的computations
集合(或数组)将填充实现Computable
的对象,即使用您的算法对象。
for(int i = 0; i < computations && !stop; i++) {
computuations.get(i).compute();
}
所以你在方法2的正确道路上,我希望你的方式现在更加明确。
干杯!
答案 1 :(得分:1)
您可以在线程上调用stop
来暂停它,而不是使用interrupt()
标记,并在run
方法内查看if (Thread.interrupted())
是否为真({{ 1}}不会立即停止线程,你仍然需要检查interrupt()
)。通过这种方式,您可以避免陷入遗忘,例如忘记将您的旗帜声明为Thread.interrupted()
。
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#interrupt%28%29
如果没有将所有计算封装在volatile
中,然后将它们放在一个数组中并循环遍历它们,那么你已经排除了,方法1是你最好的选择。至于你应该检查你的线程是否被中断的频率,这取决于你的计算运行需要多长时间以及你希望程序对Stop命令的响应程度 - 你可以添加几个Runnables
语句要了解计算的时间,然后每500毫秒左右添加一个println(System.currentTimeMillis)
来暂停if(Thread.interrupted()) return;
方法。
但是,我不会立即排除方法2,因为您的计算不需要有任何共同点,以便将它们放入run
Runnables
答案 2 :(得分:0)
根据GUI的结构,你是否有可能从GUI代码中抛出一个异常(可能是一个中断索引),这会导致漫长的过程?
关键是在代码流中寻找某处,其中的东西会出现瓶颈,可能会插入支票。这可能不是很明显(例如,你可以在一个swing应用程序中挂钩重绘管理器) - 在一般情况下它绝对不是一个好习惯 - 但对于一个非常具体的用例,它可能是合适的。
如果那是不可能的,那么稍微不那么冗长的方法就是使用这样的方法:
assertContinue() throws InterruptedException;
(或者可以称之为ac()以保持打字状态。)
你的算法仍然存在问题,但至少它输入的次数较少。
哦 - 这些计算是什么?他们是否会以某种方式阻止IO或锁定的b / c?如果是这样,那么调用Thread.interrupt()将起作用......