In attesa di più SwingWorkers

Si prega di considerare il seguente frammento di codice:

import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.InvocationTargetException; import javax.swing.*; public class TestApplet extends JApplet { @Override public void init() { try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); } }); } catch(InterruptedException | InvocationTargetException ex) { } } private void createGUI() { getContentPane().setLayout(new FlowLayout()); JButton startButton = new JButton("Do work"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformsd(ActionEvent ae) { JLabel label = new JLabel(); new Worker(label).execute(); } }); getContentPane().add(startButton); } private class Worker extends SwingWorker { JLabel label; public Worker(JLabel label) { this.label = label; } @Override protected Void doInBackground() throws Exception { // do work return null; } @Override protected void done() { getContentPane().remove(label); getContentPane().revalidate(); } } } 

Qui viene aggiunta un’etichetta all’applet che visualizza alcuni risultati intermedi del thread Worker (utilizzando i metodi di pubblicazione / processo). Alla fine, l’etichetta viene rimossa dal riquadro dell’applet. La mia domanda è: come posso creare diverse etichette, ognuna con il proprio thread di lavoro, e rimuoverle quando sono tutte fatte?

Grazie in anticipo.

AGGIORNARE:

Spero che questo chiarisca la mia domanda. Mi piacerebbe che le etichette venissero rimosse tutte in una volta, quando tutti i lavoratori hanno finito i loro compiti, non immediatamente dopo che ciascun lavoratore ha finito.

    AGGIORNAMENTO 2:

    Il seguente codice sembra fare ciò di cui ho bisogno. Si prega di commentare se l’ho fatto nel modo giusto. Ho la sensazione che ci sia qualcosa di sbagliato. Un problema è che le etichette a destra del pulsante rimangono visibili anche se vengono rimosse. setVisible (false) sembra risolvere questo problema. È questo il modo di farlo?

     import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.InvocationTargetException; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.*; public class TestApplet extends JApplet { private Queue labels = new LinkedList(); private static final Random rand = new Random(); @Override public void init() { try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); } }); } catch(InterruptedException | InvocationTargetException ex){} } private void createGUI() { getContentPane().setLayout(new FlowLayout()); JButton startButton = new JButton("Do work"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { ExecutorService executor = Executors.newFixedThreadPool(10); for(int i = 0; i < 10; i++) { JLabel label = new JLabel(); getContentPane().add(label); executor.execute(new Counter(label)); } } }); getContentPane().add(startButton); } private class Counter extends SwingWorker { private JLabel label; public Counter(JLabel label) { this.label = label; } @Override protected Void doInBackground() throws Exception { for(int i = 1; i <= 100; i++) { publish(i); Thread.sleep(rand.nextInt(80)); } return null; } @Override protected void process(List values) { label.setText(values.get(values.size() - 1).toString()); } @Override protected void done() { labels.add(label); if(labels.size() == 10) { while(!labels.isEmpty()) getContentPane().remove(labels.poll()); getContentPane().revalidate(); } } } } 

    Intendo rimuovere tutte le etichette quando tutti i lavoratori hanno completato i loro compiti.

    Come descritto qui , CountDownLatch funziona bene in questo contesto. Nell’esempio seguente, ciascun worker richiama latch.countDown() al completamento e un worker Supervisor blocca latch.await() fino al completamento di tutte le attività. A fini dimostrativi, il Supervisor aggiorna le etichette. La rimozione all’ingrosso, mostrata nei commenti, è tecnicamente ansible ma generalmente poco attraente. Invece, considera una JList o una JTable .

    Worker Latch Test

     import java.awt.Color; import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.*; /** * @see https://stackoverflow.com/a/11372932/230513 * @see https://stackoverflow.com/a/3588523/230513 */ public class WorkerLatchTest extends JApplet { private static final int N = 8; private static final Random rand = new Random(); private Queue labels = new LinkedList(); private JPanel panel = new JPanel(new GridLayout(0, 1)); private JButton startButton = new JButton(new StartAction("Do work")); public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame(); frame.setTitle("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new WorkerLatchTest().createGUI()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } @Override public void init() { EventQueue.invokeLater(new Runnable() { @Override public void run() { add(new WorkerLatchTest().createGUI()); } }); } private JPanel createGUI() { for (int i = 0; i < N; i++) { JLabel label = new JLabel("0", JLabel.CENTER); label.setOpaque(true); panel.add(label); labels.add(label); } panel.add(startButton); return panel; } private class StartAction extends AbstractAction { private StartAction(String name) { super(name); } @Override public void actionPerformed(ActionEvent e) { startButton.setEnabled(false); CountDownLatch latch = new CountDownLatch(N); ExecutorService executor = Executors.newFixedThreadPool(N); for (JLabel label : labels) { label.setBackground(Color.white); executor.execute(new Counter(label, latch)); } new Supervisor(latch).execute(); } } private class Supervisor extends SwingWorker { CountDownLatch latch; public Supervisor(CountDownLatch latch) { this.latch = latch; } @Override protected Void doInBackground() throws Exception { latch.await(); return null; } @Override protected void done() { for (JLabel label : labels) { label.setText("Fin!"); label.setBackground(Color.lightGray); } startButton.setEnabled(true); //panel.removeAll(); panel.revalidate(); panel.repaint(); } } private static class Counter extends SwingWorker { private JLabel label; CountDownLatch latch; public Counter(JLabel label, CountDownLatch latch) { this.label = label; this.latch = latch; } @Override protected Void doInBackground() throws Exception { int latency = rand.nextInt(42) + 10; for (int i = 1; i <= 100; i++) { publish(i); Thread.sleep(latency); } return null; } @Override protected void process(List values) { label.setText(values.get(values.size() - 1).toString()); } @Override protected void done() { label.setBackground(Color.green); latch.countDown(); } } } 

    Il codice che hai già lo sta facendo in una certa misura. È necessario aggiungere effettivamente l’etichetta al contenuto quando si fa clic sul pulsante. Qualcosa come questo:

      JLabel label = new JLabel(); getContentPane().add(label); getContentPane().validate(); new Worker(label).execute(); 

    Potrebbe essere una buona idea inserire del testo nell’etichetta in modo da vederlo effettivamente quando viene aggiunto allo schermo.

      JLabel label = new JLabel("Hello...I am here"); 

    E infine nel metodo doInBackground () puoi aggiungere del codice per aggiornare l’etichetta mentre alcune attività sono in esecuzione:

      for(int i = 0;i < 100; i++){ Thread.sleep(20); label.setText("Counting..." + i); } 

    In questo modo si vede effettivamente l'attività in esecuzione. Se si fa clic sul pulsante più volte, vengono visualizzate più etichette e ciascuna scompare dopo il completamento dell'attività.