什么是最安全/最好的方法来停止一个线程并运行一些清理代码

时间:2014-07-23 07:58:31

标签: java concurrency cmusphinx

作为我在Java中实现语音识别程序的努力的一部分,我已经在一个单独的线程中实现了实际的语音识别代码。主线程处理GUI界面,并在识别出单词时从语音识别线程接收持续更新。

当用户在主线程的GUI中单击Quit按钮时,我希望此线程立即运行一些清理代码并终止。

我目前有以下内容:

public class VoiceRecognitionCore extends SwingWorker<List<String>, String>
{
    //Variables and things here

    @Override
    public List<String> doInBackground() throws VoiceRecognitionException
    {
        //Code here
        while(continueVoiceRecog == true)
        {
             //More code
             Result result = recog.recognize();
             //More code
        }
    }
}

我依赖while循环来不断检查continueVoiceRecog的状态,当用户点击“Quit”时,主线程将设置为false。

当前的问题是代码有时会永久地位于recog.recognize()方法内部,因此它永远不会返回到while检查。应该指出的是,这始终是一种临时解决方案。

我正在考虑扩展doInBackground()以捕获InterruptedException,并将使用一个线程中断来调用一个清理方法来释放正在使用的任何资源。

此方案的最安全/最佳方法是什么?如果这是我的建议,我应该注意哪些潜在的问题?

1 个答案:

答案 0 :(得分:1)

使用线程中断是完全可以接受的路径 - 但是在您的示例中(使用SwingWorker),您可以使用cancel()方法。

在创建VoiceRecognitionCore后的调用代码中,您可以cancel()工作人员退出按钮动作监听器:

    final VoiceRecognitionCore worker = new VoicRecognitionCore();
    worker.execute();

    JButton exitButton = new JButton("Exit");
    exitButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // True passed to Interrupt the underlying thread.
            worker.cancel(true);
            // other clean-up
            // then System.exit(0); ?
        }
    });

但是,这种方法需要在recognize()方法中检查:Thread.isInterrupted()的状态。 (见链接:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/cancel.html

如果您需要清理内容并且无法检查isInterrupted()标记 - 也许最好的方法是找到一种方法来确定您的recog对象是中间识别...当按下退出按钮时 - 如果recog.isRecognizing()然后清理然后退出?

PS。有人可能会说,如果你正在做一个System.exit(0);无论如何,然后干净地退出那个循环可能是不必要的......但这取决于你是否正在那里进行其他清理......例如完成对文件的写入等。

相关问题