请考虑以下代码片段:
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 actionPerformed(ActionEvent ae) { JLabel label = new JLabel(); new Worker(label).execute(); } }); getContentPane().add(startButton); } private class Worker extends SwingWorker<Void,Void> { 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(); } } }
这是向applet添加一个标签,显示Worker线程的一些中间结果(使用publish / process方法).最后,标签从小应用程序的窗格中删除.我的问题是,我如何创建几个标签,每个标签都有自己的工作线程,并在完成后删除它们?
提前致谢.
更新:
我希望这将澄清我的问题.当所有的工作人员都完成了任务,而不是在每个工作人员完成后立即将标签全部删除.
更新2:
以下代码似乎正在做我需要的.请评论我是否做了正确的方法.我有一种感觉有什么问题.一个问题是,除去删除按钮之后,按钮右侧的标签仍然可见. setVisible(false)似乎解决了这个问题.是这样做吗?
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<JLabel> 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<Void,Integer> { 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<Integer> 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(); } } } }
解决方法
I intend to remove all of the labels together when all of the workers have completed their tasks.
如here所述,CountDownLatch在此上下文中工作良好.在下面的示例中,每个工作人员在完成时调用latch.countDown(),并且Supervisor工作程序阻塞latch.await(),直到所有任务完成.为了演示目的,主管更新标签.批评删除,在评论中显示,在技术上是可能的,但通常没有吸引力.相反,请考虑一个JList或JTable.
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<JLabel> labels = new LinkedList<JLabel>(); 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<Void,Void> { 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<Void,Integer> { 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<Integer> values) { label.setText(values.get(values.size() - 1).toString()); } @Override protected void done() { label.setBackground(Color.green); latch.countDown(); } } }