请考虑以下代码片段:
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();
}
}
}
下面是向小程序添加一个标签,该标签显示工作线程的一些中间结果(使用发布/处理方法)。最后,标签将从小程序的窗格中移除。我的问题是,我如何创建几个标签,每个标签都有自己的工作线程,并在全部完成后删除它们?
提前感谢。
更新:
我希望这能澄清我的问题。我希望在所有工人完成任务后,而不是在每个工人完成任务后立即移除所有标签。
更新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();
}
}
}
}
您所拥有的代码已经在一定程度上做到了这一点。当单击按钮时,您实际上需要将标签添加到内容窗格中。类似于这样:
JLabel label = new JLabel();
getContentPane().add(label);
getContentPane().validate();
new Worker(label).execute();
在标签中添加一些文本可能是个好主意,这样当它添加到屏幕上时,你就可以真正看到它。
JLabel label = new JLabel("Hello...I am here");
最后,在doInBackground()方法中,您可以添加一些代码,以便在某些任务运行时更新标签:
for(int i = 0;i < 100; i++){
Thread.sleep(20);
label.setText("Counting..." + i);
}
这样你就能看到任务在运行。如果多次单击该按钮,您会看到多个标签,并且在任务完成后它们都会消失。
我打算在所有工人完成任务后,一起移除所有标签。
如本文所述,倒计时闩锁
在这种情况下工作良好。在下面的示例中,每个工人调用闩锁。倒计时()
完成后,一名主管
工作人员阻塞闩锁。等待()
直到所有任务完成。出于演示目的,主管更新标签。从评论中可以看出,从技术上讲,大规模移除是可行的,但通常不具吸引力。相反,请考虑<代码> jList或<代码> jTabe>代码>。
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();
}
}
}
问题内容: 请考虑以下代码片段: 这是在小程序中添加一个标签,该标签显示了Worker线程的一些中间结果(使用发布/处理方法)。最后,标签从小程序的窗格中删除。我的问题是,如何创建多个标签,每个标签都有自己的Worker线程,并在完成标签后将其删除? 提前致谢。 更新: 我希望这可以澄清我的问题。我希望在所有工作人员都完成任务后立即删除所有标签,而不是在每个工作人员都完成之后立即删除。 更新2:
问题内容: 如何更改以下代码,以触发两个异步操作并有机会同时运行? 我需要做这样的事情吗? 问题答案: TL; DR 不要在获得承诺的问题中使用模式,而是分别等待它们;而是使用(至少现在): 虽然您的解决方案 确实 并行运行这两个操作,但如果两个诺言都被拒绝,它就无法正确处理拒绝。 细节: 您的解决方案并行运行它们,但始终等待第一个完成,然后再等待第二个。 如果您只想启动它们,并行运行它们,并获得
问题内容: 我如何更改以下代码,以触发两个异步操作并有机会同时运行? 我需要做这样的事情吗? 问题答案: TL; DR 不要在获得承诺的问题中使用模式,而是分别等待它们;而是使用(至少现在): 虽然您的解决方案确实并行运行这两个操作,但是如果两个诺言都被拒绝,它就无法正确处理拒绝。 细节: 您的解决方案并行运行它们,但始终等待第一个完成,然后再等待第二个。如果您只想启动它们,并行运行它们,并获得两
我想运行相同类型的任务(工作线程),但一次不超过一定数量的任务。当任务完成时,其结果是新任务的输入,然后可以启动该任务。 有没有好的方法可以在C 11中使用异步/未来范式来实现这一点? 乍一看,它看起来很简单,你只是生成多个任务: 然后,运行以获取任务的异步结果。 然而,这里的问题是,未来的对象必须存储在某种队列中并一个接一个地等待。但是,可以一遍又一遍地迭代未来的对象,检查它们中的任何一个是否准
问题内容: 我通过将操作拆分为可用的确切内核数来并行化操作,然后通过启动相同数量的AsyncTask,对数据的不同部分执行相同的操作。 我正在使用以并行化它们的执行。 我想知道每个线程何时完成其工作,以便结合所有结果并执行进一步的操作。 我能怎么做? 问题答案: 您还可以简单地将共享库中的计数器递减作为的一部分。由于在同一线程(主线程)上运行,因此您不必担心同步。 更新1 共享对象可能看起来像这样
问题内容: 我正在寻找一种方法来异步执行go中的两个函数,该函数返回不同的结果和错误,等待它们完成并打印两个结果。另外,如果一个函数返回错误,我不想等待另一个函数,只打印错误。例如,我具有以下功能: 这里https://play.golang.org/p/-8StYapmlg是我是如何实现它,但是它有太多的代码,我想。可以通过使用interface {}来简化它,但是我不想这样。我想要更简单的东西