2012-04-30 20 views
5

Tôi có nhiều lớp mở rộng SwingWorker. Những gì tôi muốn thực hiện là thực thi từng lớp một (không thực hiện lớp tiếp theo trong phương thức thực hiện của lớp trước). Ví dụ, cho phép nói rằng tôi có:java - thực hiện từng lớp SwingWorker một cái khác

ClassSwingW1 csw1 = new ClassSwingW1(); 
csw1.execute; 

ClassSwingW2 csw2 = new ClassSwingW2(); 
csw2.execute; 

ClassSwingW3 csw3 = new ClassSwingW3(); 
csw3.execute; 

và vv

public class ClassSwingW1 extends SwingWorker<Void, Void> { 

    @Override 
    protected Void doInBackground() throws Exception { 
     //do something 

     return null; 
    } 

} 

public class ClassSwingW2 extends SwingWorker<Void, Void> { 

    @Override 
    protected Void doInBackground() throws Exception { 
     //do something 

     return null; 
    } 

} 

public class ClassSwingW3 extends SwingWorker<Void, Void> { 

    @Override 
    protected Void doInBackground() throws Exception { 
     //do something 

     return null; 
    } 

} 

Tôi muốn csw2 để thực hiện sau khi csw1 được thực hiện, và csw3 để thực hiện sau khi csw2 được thực hiện. Tôi không muốn họ thực hiện cùng một lúc. Làm thế nào tôi sẽ thực hiện được điều này? Cảm ơn bạn

+2

Có bắt buộc phải sử dụng các lớp con của 'SwingWorker'? Nó có liên quan. –

Trả lời

3

Bạn có thể sử dụng get() method thay vì execute() - nó sẽ chặn cho đến khi SwingWorker kết thúc công việc của mình. Chỉ cần chắc chắn rằng bạn không gọi nó từ EDT.

Javadoc chiết xuất:

Waits nếu cần thiết cho việc tính toán để hoàn thành, và sau đó lấy kết quả của nó. Lưu ý: cuộc gọi nhận được trên Event Dispatch Thread chặn tất cả các sự kiện, bao gồm cả repaints, từ đang được xử lý cho đến khi SwingWorker này hoàn tất.

+0

[lý do sử dụng phương thức get()] (http://stackoverflow.com/questions/7053865/cant-get-arrayindexoutofboundsexception-from-future-and-swingworker-if-threa) – mKorbel

3
  • Tôi muốn được đề nghị nhìn vào Executor gọi một ví dụ SwingWorker, bằng cách lắng nghe từ PropertyChangeListener

  • xin read carrefully this thread, đặc biệt là các câu trả lời bằng @trashgod

Executor & SwingWorker & PropertyChangeListener & Swing GUI

enter image description here

enter image description here

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.List; 
import java.util.Random; 
import java.util.concurrent.Executor; 
import java.util.concurrent.Executors; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 
import javax.swing.Timer; 
import javax.swing.border.EmptyBorder; 

public class ExecutorAndSwingWorker2 { 

    private JFrame frame = new JFrame(); 
    private JButton button1; 
    private JButton button2; 
    private JButton button3; 
    private JButton button4; 
    private JPanel buttonPanel = new JPanel(); 
    private Executor executor = Executors.newCachedThreadPool(); 
    private javax.swing.Timer timer1; 
    private javax.swing.Timer timer2; 
    private javax.swing.Timer timer3; 
    private javax.swing.Timer timer4; 
    private Random random = new Random(); 

    public ExecutorAndSwingWorker2() { 
     button1 = new JButton(" Executor + SwingWorker Thread No.1 "); 
     button1.setFocusable(false); 
     button2 = new JButton(" Executor + SwingWorker Thread No.2 "); 
     button3 = new JButton(" Executor + SwingWorker Thread No.3 "); 
     button4 = new JButton(" Executor + SwingWorker Thread No.4 "); 
     buttonPanel = new JPanel(); 
     buttonPanel.setBorder(new EmptyBorder(15, 15, 15, 15)); 
     buttonPanel.setLayout(new GridLayout(2, 2, 20, 20)); 
     buttonPanel.add(button1); 
     buttonPanel.add(button2); 
     buttonPanel.add(button3); 
     buttonPanel.add(button4); 
     frame.setTitle("Shaking Button Demo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLayout(new BorderLayout()); 
     frame.add(buttonPanel); 
     frame.setPreferredSize(new Dimension(700, 170)); 
     frame.setLocation(150, 100); 
     frame.pack(); 
     frame.setVisible(true); 
     executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT 
    } 

    private void startButton1() { 
     System.out.println("Starting long Thread == startButton1()"); 
     try { 
      Thread.sleep(15000); 
     } catch (InterruptedException ex) { 
     } 
    } 

    private void startButton2() { 
     System.out.println("Starting long Thread == startButton2()"); 
     try { 
      Thread.sleep(17500); 
     } catch (InterruptedException ex) { 
     } 
    } 

    private void startButton3() { 
     System.out.println("Starting long Thread == startButton3()"); 
     try { 
      Thread.sleep(12500); 
     } catch (InterruptedException ex) { 
     } 
    } 

    private void startButton4() { 
     System.out.println("Starting long Thread == startButton4()"); 
     try { 
      Thread.sleep(20000); 
     } catch (InterruptedException ex) { 
     } 
    } 

    private void colorAction1() { 
     timer1 = new Timer(1000, new AbstractAction() { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       random = new Random(); 
       SwingUtilities.invokeLater(new Runnable() { 

        @Override 
        public void run() { 
         button1.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); 
         button1.validate(); 
         button1.repaint(); 
        } 
       }); 
      } 
     }); 
     timer1.setDelay(500); 
     timer1.setRepeats(true); 
     timer1.start(); 
    } 

    private void colorAction2() { 
     timer2 = new Timer(1200, new AbstractAction() { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       random = new Random(); 
       SwingUtilities.invokeLater(new Runnable() { 

        @Override 
        public void run() { 
         button2.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); 
         button2.validate(); 
         button2.repaint(); 
        } 
       }); 
      } 
     }); 
     timer2.setDelay(500); 
     timer2.setRepeats(true); 
     timer2.start(); 
    } 

    private void colorAction3() { 
     timer3 = new Timer(1400, new AbstractAction() { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       random = new Random(); 
       SwingUtilities.invokeLater(new Runnable() { 

        @Override 
        public void run() { 
         button3.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); 
         button3.validate(); 
         button3.repaint(); 
        } 
       }); 
      } 
     }); 
     timer3.setDelay(500); 
     timer3.setRepeats(true); 
     timer3.start(); 
    } 

    private void colorAction4() { 
     timer4 = new Timer(1600, new AbstractAction() { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       random = new Random(); 
       SwingUtilities.invokeLater(new Runnable() { 

        @Override 
        public void run() { 
         button4.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); 
         button4.validate(); 
         button4.repaint(); 
        } 
       }); 
      } 
     }); 
     timer4.setDelay(500); 
     timer4.setRepeats(true); 
     timer4.start(); 
    } 

    private void endButton1() { 
     timer1.stop(); 
     button1.setBackground(null); 
     System.out.println("Long Thread Ends == startButton1()"); 
     executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton3")); // non on EDT 
    } 

    private void endButton2() { 
     timer2.stop(); 
     button2.setBackground(null); 
     System.out.println("Long Thread Ends == startButton2()"); 
    } 

    private void endButton3() { 
     timer3.stop(); 
     button3.setBackground(null); 
     System.out.println("Long Thread Ends == startButton3()"); 
     executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton2")); // non on EDT 
     executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton4")); // non on EDT 
    } 

    private void endButton4() { 
     timer4.stop(); 
     button4.setBackground(null); 
     System.out.println("Long Thread Ends == startButton4()"); 
     executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT 
    } 

    private class MyTask extends SwingWorker<Void, Integer> { 

     private String str; 
     private String namePr; 
     private JDialog dialog = new JDialog(); 

     MyTask(String str) { 
      this.str = str; 
      addPropertyChangeListener(new SwingWorkerCompletionWaiter(dialog, str, namePr)); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      if (str.equals("startButton1")) { 
       colorAction1(); 
       startButton1(); 
      } else if (str.equals("startButton2")) { 
       colorAction2(); 
       startButton2(); 
      } else if (str.equals("startButton3")) { 
       colorAction3(); 
       startButton3(); 
      } else if (str.equals("startButton4")) { 
       colorAction4(); 
       startButton4(); 
      } 
      return null; 
     } 

     @Override 
     protected void process(List<Integer> progress) { 
      System.out.println(str + " " + progress.get(progress.size() - 1)); 
     } 

     @Override 
     protected void done() { 
      if (str.equals("startButton1")) { 
       endButton1(); 
      } else if (str.equals("startButton2")) { 
       endButton2(); 
      } else if (str.equals("startButton3")) { 
       endButton3(); 
      } else if (str.equals("startButton4")) { 
       endButton4(); 
      } 
     } 
    } 

    private class SwingWorkerCompletionWaiter implements PropertyChangeListener { 

     private JDialog dialog; 
     private String str; 
     private String namePr; 

     SwingWorkerCompletionWaiter(JDialog dialog, String str, String namePr) { 
      this.dialog = dialog; 
      this.str = str; 
      this.namePr = namePr; 
     } 

     @Override 
     public void propertyChange(PropertyChangeEvent event) { 
      if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) { 
       System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); 
      } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) { 
       System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue()); 
      } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) { 
       System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); 
      } else { 
       System.out.println("Thread Status with Name :" + str + ", Something wrong happends "); 
      } 
     } 
    } 

    public static void main(String[] args) { 

     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       ExecutorAndSwingWorker2 executorAndSwingWorker = new ExecutorAndSwingWorker2(); 
      } 
     }); 
    } 
} 

với sản lượng từ PropertyChangeListener

Starting long Thread == startButton1() 
Thread Status with Name :startButton1, SwingWorker Status is STARTED 
Long Thread Ends == startButton1() 
Thread Status with Name :startButton1, SwingWorker Status is DONE 
Starting long Thread == startButton3() 
Thread Status with Name :startButton3, SwingWorker Status is STARTED 
Long Thread Ends == startButton3() 
Thread Status with Name :startButton3, SwingWorker Status is DONE 
Starting long Thread == startButton2() 
Starting long Thread == startButton4() 
Thread Status with Name :startButton2, SwingWorker Status is STARTED 
Thread Status with Name :startButton4, SwingWorker Status is STARTED 
Long Thread Ends == startButton2() 
Thread Status with Name :startButton2, SwingWorker Status is DONE 
Long Thread Ends == startButton4() 
Thread Status with Name :startButton4, SwingWorker Status is DONE 
Starting long Thread == startButton1() 
Thread Status with Name :startButton1, SwingWorker Status is STARTED 
Long Thread Ends == startButton1() 
Thread Status with Name :startButton1, SwingWorker Status is DONE 
Starting long Thread == startButton3() 
Thread Status with Name :startButton3, SwingWorker Status is STARTED 
Long Thread Ends == startButton3() 
Starting long Thread == startButton2() 
Thread Status with Name :startButton3, SwingWorker Status is DONE 
Starting long Thread == startButton4() 
Thread Status with Name :startButton2, SwingWorker Status is STARTED 
Thread Status with Name :startButton4, SwingWorker Status is STARTED 
Long Thread Ends == startButton2() 
Thread Status with Name :startButton2, SwingWorker Status is DONE 
BUILD SUCCESSFUL (total time: 1 minute 34 seconds) 
2

Memory Consistency Properties tóm tắt JLS: "Mỗi hành động trong một chủ đề xảy ra trước mọi hành động trong chuỗi đó đến sau trong thứ tự của chương trình". Đơn giản chỉ cần tái yếu tố của từng người lao động doInBackground() thành một phương pháp riêng, và gọi nhau theo thứ tự:

@Override 
protected Void doInBackground() throws Exception { 
    doCsw1(); 
    doCsw2(); 
    doCsw3(); 
    return null; 
} 
2

Làm thế nào về việc sử dụng Executors.newSingleThreadExecutor()

import java.awt.*; 
import java.awt.event.*; 
import java.beans.*; 
import java.util.*; 
import java.util.concurrent.*; 
import javax.swing.*; 

public class SingleThreadExecutorTest { 
    private Executor executor; 
    private final Box box = Box.createVerticalBox(); 
    public JComponent makeUI() { 
    executor = Executors.newSingleThreadExecutor(); //.newCachedThreadPool(); 
    box.setBorder(BorderFactory.createEmptyBorder(8,8,8,8)); 
    JPanel p = new JPanel(new BorderLayout()); 
    p.add(new JButton(new AbstractAction("add") { 
     @Override public void actionPerformed(ActionEvent evt) { 
     doSomethingUseful(); 
     } 
    }), BorderLayout.SOUTH); 
    p.add(new JScrollPane(box)); 
    return p; 
    } 
    private void doSomethingUseful() { 
    JProgressBar bar = new JProgressBar(0, 100); 
    box.add(bar); box.add(Box.createVerticalStrut(8)); 
    box.revalidate(); 
    SwingWorker<Integer, Void> worker = new SwingWorker<Integer, Void>() { 
     private int sleepDummy = new Random().nextInt(50) + 1; 
     private int lengthOfTask = 120; 
     @Override protected Integer doInBackground() { 
     int current = 0; 
     while(current<lengthOfTask && !isCancelled()) { 
      current++; 
      try { 
      Thread.sleep(sleepDummy); 
      } catch(InterruptedException ie) { 
      break; 
      } 
      setProgress(100 * current/lengthOfTask); 
     } 
     return sleepDummy*lengthOfTask; 
     } 
     @Override protected void done() { 
     try { 
      System.out.println(get()+"ms"); 
     } catch(Exception ignore) { 
      ignore.printStackTrace(); 
     } 
     } 
    }; 
    worker.addPropertyChangeListener(new ProgressListener(bar)); 
    executor.execute(worker); 
    } 
    public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override public void run() { 
     createAndShowGUI(); 
     } 
    }); 
    } 
    public static void createAndShowGUI() { 
    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    f.getContentPane().add(new SingleThreadExecutorTest().makeUI()); 
    f.setSize(320, 240); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 
class ProgressListener implements PropertyChangeListener { 
    private final JProgressBar progressBar; 
    ProgressListener(JProgressBar progressBar) { 
    this.progressBar = progressBar; 
    this.progressBar.setValue(0); 
    } 
    @Override public void propertyChange(PropertyChangeEvent evt) { 
    String strPropertyName = evt.getPropertyName(); 
    if("progress".equals(strPropertyName)) { 
     progressBar.setIndeterminate(false); 
     int progress = (Integer)evt.getNewValue(); 
     progressBar.setValue(progress); 
    } 
    } 
}