Java - 终止Thread中的方法

时间:2014-02-12 03:33:02

标签: java multithreading

我有一个带有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()方法只是变量代码的一种巨大方法。


还有其他解决方案吗?这似乎应该是一个普遍的问题。提前谢谢!

3 个答案:

答案 0 :(得分:5)

你想要做的事情实际上可以通过方法2完成,但你必须使用Strategy Pattern,这真的是你需要的一件事,因为它可以在一行中简化你的计算就像你在方法2中所做的一样。

它的工作方式如下,它允许您通过执行多态来更改下一个可执行算法。

enter image description here

首先,您必须在不同的类中制作所有算法,并且每个算法都必须使用一种方法(即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()将起作用......