从JButtonActionPerformed调用一个耗时的方法

时间:2012-09-10 18:08:59

标签: java multithreading swing jbutton event-dispatch-thread

在按下Button1时的以下代码行中,Jframe变得无响应,直到encode()方法的执行完成。但是我需要在Jframe中更新显示进度的进度条。

private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {                                   
    try {
        if (flagState == 0) {
            WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
        } else if (flagState == 1) {
            WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode());            
        }
    } catch (WavFileException | IOException e) {
        notes.setText(e.getMessage());
    }
}         

我想过这样做

private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {                                   
    try {
        if (flagState == 0) {
            Thread t = new Thread(new Runnable() {
                               public void run() {
                                  WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode()); 
                               }
                            };)
            t.start();
        } else if (flagState == 1) {
            Thread t = new Thread(new Runnable() {
                               public void run() {
                                  WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode()); 
                               }
                            };)
            t.start();
        }
    } catch (WavFileException | IOException e) {
        notes.setText(e.getMessage());
    }
} 

并从encode()方法更新进度条。

但我明白,这将是模块之间的强大耦合,我不希望这样。

我也不认为每次调用一个新线程都是个好主意(想到ExecutorService但不知道如何使用它)。

我该怎么做才能把它变成一个体面的片段代码?

3 个答案:

答案 0 :(得分:1)

  

在按下Button1时,以下代码行,Jframe变得无响应,直到encode()方法的执行完成。但是我需要在Jframe中更新显示进度的进度条。

您遇到Concurency in Swing的问题,block the EDT导致无法响应的GUI,直到代码结束

答案 1 :(得分:1)

线程绝对是你必须在这里介绍的东西。任何需要花费大量时间才能完成的事情都不应该在awt事件线程中运行。

每次单击按钮时生成一个新线程本身并不是问题。但是,您应该考虑,即使在第一次完成之前,也可能会生成许多执行相同操作的线程。如果需要,可以使用Executor,但可能没有必要。

至于跟踪进度,我会添加另一个线程,定期查询其他线程并根据需要更新进度条。以下是我将如何构建它:

private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
    disableButton1();
    final Thread t;
    if (flagState == 0) {
        t = new Thread(new Runnable() {
            public void run() {
                try {
                    WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
                } catch (WavFileException | IOException e) {
                    notes.setText(e.getMessage());
                }
            }
        });
    } else if (flagState == 1) {
        t = new Thread(new Runnable() {
            public void run() {
                try {
                    WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode()); 
                } catch (WavFileException | IOException e) {
                    notes.setText(e.getMessage());
                }
            }
        });
    }

    Thread monitor = new Thread(new Runnable() {
        public void run() {
            try {
                while (notComplete(t)) {
                    setProgressBar(getProgress(t));
                    Thread.sleep(SLEEP_TIME);
                }
                t.join();
            } finally {
                enableButton1();
            }
        }
    });

    t.start();
    monitor.start();
}

答案 2 :(得分:0)

多线程是你需要的,没有其他好的方法我可以想到不要担心调用新线程,这就是它们的用途,jvm有一个线程池可供使用,这种事情运行非常好用线程,试一试!

创建一个扩展Runnable的类,实现run方法或让它调用当前方法,这应该就足够了。

此外,您可以让它短时间睡眠并在每次睡眠时间结束时检查状态,如果过程结束,您可以继续,如果没有,则再次进入睡眠状态,这样您就不会我不得不问过很多次。

我希望它有所帮助。