Java - 如何通过GUI安全地停止Web应用程序中的线程?

3

有没有一种安全并立即停止Java中线程执行的方法?特别是,如果实现Runnable内的run()方法只执行了单一迭代,并且不定期检查任何告诉它停止的标志?

我正在构建一个Web应用程序,用户可以使用它将整个文档的内容从一种语言翻译成另一种语言。

假设文档很大,并且随后假设每个翻译需要很长时间(比如20-25分钟),我的应用程序为由其用户发起的每个翻译创建一个单独的线程。用户可以查看活动翻译列表,并决定停止特定的翻译作业。

这是我的Translator.java

public class Translator {
   public void translate(File file, String sourceLanguage, String targetLanguage) {
    //Translation happens here
    //.......
    //Translation ends and a new File is created.
   }

}

我创建了一个名为TranslatorRunnable的类,它实现了以下Runnable接口:
public class TranslatorRunnable implements Runnable {

    private File document;
    private String sourceLanguage;
    private String targetLanguage;

    public TranslatorRunnable(File document, String sourceLanguage, String targetLanguage) {
        this.document = document;
        this.sourceLanguage = sourceLanguage;
        this.targetLanguage = targetLanguage;
    }

    public void run() {
        // TODO Auto-generated method stub
        Translator translator = new Translator();
        translator.translate(this.document, this.sourceLanguage, this.targetLanguage);
        System.out.println("Translator thread is finished.");
    }

}

我正在创建一个线程,用于从外部类翻译文档,代码如下:
TranslatorRunnable tRunnable = new TranslatorRunnable(document, "ENGLISH", "FRENCH");
Thread t = new Thread(tRunnable);
t.start();

现在我的问题是,当用户在GUI中点击“停止”时,如何停止翻译过程(本质上是一个线程)?

我已经阅读了StackOverflow和其他网站上的一些帖子,告诉我在Runnable实现内部有一个易失性布尔标志,我应该从run()方法内部定期检查它,并决定何时停止。请参见此帖子

对我来说,这行不通,因为run()方法只是调用Translator.translate()方法,而Translator.translate()方法本身将需要很长时间。我在这里没有选择。

接下来我读到的是使用ExecutorService并使用其shutDownAll()方法。但即使在这里,我也必须在我的代码中定期处理InterruptedException。这又是不可选的。参考ExecutorService类的此文档

我知道我不能使用Thread.stop(),因为它已经被弃用,并且可能会对所有线程常用的对象造成问题。

我有哪些选择?

如果没有对我的设计进行重大更改,我的要求是否真的可行?如果是,请告诉我如何做到。

如果必须更改设计,有谁能告诉我最好的方法是什么?

谢谢, Sriram


你可以使用 t.interrupt()。 - Debu
2个回答

2

在Java中,有没有一种安全且立即停止线程执行的方法?

没有。每个线程都负责定期检查是否已被中断以尽快退出。

if (Thread.currentThread().isInterrupted() ) {
  // release resources. finish quickly what it was doing
}

如果你想让应用程序更加响应,请改变逻辑(例如将每个任务分成较小的批次),这样每个线程检查的频率比每20-25分钟更高。


0
如果您是创建Translator类的人,那么有什么阻止您在函数内添加某种值,定期进行检查,并在需要时停止从文件中读取行,就像这样。
   public static List<String> readFile(String filename)
{
    List<String> records = new ArrayList<>();
    try
    {
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String line;
        while ((line = reader.readLine()) != null)
        {
            String[] split = line.split("\\s+");
            records.addAll(Arrays.asList(split));
            if (needsToStop) {
                break; //Or throw exception
            }
        }
        reader.close();
        return records;
    }
    catch (Exception e)
    {
        System.err.format("Exception occurred trying to read '%s'.", filename);
        e.printStackTrace();
        return null;
    }
}

这并不是那么简单,因为translate()方法反过来调用许多其他类、方法和库,每个都可能增加执行时间。因此,如果我希望我的应用程序在用户点击停止按钮时响应灵敏,就不能这样做。 - Sriram Sridharan
代码中是否有任何需要很长时间而且你无法控制的部分,还是所有东西都在你的掌控之下? - urag
translate() 方法会调用一个大部分任务都由库完成的程序,而我对此没有任何控制权。除了调用这些库之外,在 translate() 方法内,我唯一能做的就是更新翻译状态(这也是我唯一有控制权的地方)。 - Sriram Sridharan
你能否将输入分块传递给这个库,而不是一次性全部传递? - urag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接