Java SwingWorker并发问题

时间:2013-11-05 17:10:26

标签: java swing concurrency stdout swingworker

我有一个执行文件操作的java程序,我有一个GUI类,它有一个JTextArea,控制台输出重定向到它。我试图让SwingWorker在另一个类中发布到该JTextArea但我似乎无法让它正常工作。在我的GUI类中,我有以下方法:

public ShopUpdaterGUI() {
    initComponents();
    redirectSystemStreams();
}

private void updateTextArea(final String text) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            consoleTextAreaInner.append(text);
          }
        });
}


private void redirectSystemStreams() {
      OutputStream out = new OutputStream() {
        @Override
        public void write(int b) throws IOException {
          updateTextArea(String.valueOf((char) b));
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
          updateTextArea(new String(b, off, len));
        }

        @Override
        public void write(byte[] b) throws IOException {
          write(b, 0, b.length);
        }
      };

      System.setOut(new PrintStream(out, true));
      System.setErr(new PrintStream(out, true));
    }    

然后在我完成这项工作的其他班级中:

public void update(){
    (updateTask = new UpdateTask()).execute();
}

private class UpdateTask extends SwingWorker<Void, String>{

        @Override
        protected Void doInBackground() {
            try{
                publish("Creating backup...");
                mainBackup.createBackup();
                publish("Setting restore point...");
                setRestorePoint();
                publish("Applying update...");
                UPDHandler.unZipUpdate();
                saveModifiedFilesList();

            }catch(IOException ex){
                ex.printStackTrace();
            }catch(ClassNotFoundException ex){
                ex.printStackTrace();
            }finally{
                publish("Update Complete!");
            }

            return null;
        }


}

编辑:这是我的处理方法:

    protected void process(List<String> updates){
        String update = updates.get(updates.size() - 1);
        System.out.println(update);
    }

这有时会起作用,但有时它会完全跳过其中一个publish()调用。例如,当它到达发布(“设置还原点...”)时,它实际上永远不会显示在JTextArea上,而是会跳到“应用更新...”

如何在我告诉它时准确发布和更新JTextArea?

2 个答案:

答案 0 :(得分:2)

publish(V... chunks)中使用

doInBackground()将数据发送到process(List<V> chunks)以在GUI线程中处理它们。你错过的是重写过程方法:

@Override
 protected void process(List<String> chunks) {
     for (String s : chunks) {
         textArea.append(s + "\n");
     }
 }

答案 1 :(得分:2)

不要发布或处理任何内容。在您的情况下,因为您的JTextArea正在接收从System.out重定向的输出,所以您需要做的就是在需要在JTextArea中显示的文本上调用System.out.println(...)

private class UpdateTask extends SwingWorker<Void, String>{

    @Override
    protected Void doInBackground() {
        try{
            publish("Creating backup...");
            mainBackup.createBackup();

            // publish("Setting restore point...");
            System.out.println("Setting restore point...");

            setRestorePoint();

            // publish("Applying update...");
            System.out.println("Applying update...");

            UPDHandler.unZipUpdate();
            saveModifiedFilesList();

        }catch(IOException ex){
            ex.printStackTrace();
        }catch(ClassNotFoundException ex){
            ex.printStackTrace();
        }finally{
            publish("Update Complete!");
        }

        return null;
    }
}

请参阅this answer中的代码,以获取包含后台线程使用情况的更完整示例。