我有2个进程在我的挥杆应用,以执行一个填充列表,和一个做在列表上的每个元件上的操作。我刚搬了2个进程进入的SwingWorker线程,而任务执行停止GUI锁定了,因为我需要这组操作做几个列表,所以并发不会在第一个坏主意地点。然而,当我刚跑

  

fillList.execute();结果,doStuffToList.execute();

在doStuffToList线程跑空的列表(废话...)上。我如何告诉第二个进程等到第一个是做了什么?我想我可以只窝在第一个结束的第二个过程,但我不知道,这似乎是不好的做法。

有帮助吗?

解决方案

像这样的事情会做到这一点,我认为?

boolean listIsFull=false;
class FillListWorker extends SwingWorker<Foo,Bar>
{
    ...
    protected void done()
    {
        synchronized (listYouveBeenFilling)
        {
            listIsFull=true;
            listYouveBeenFilling.notifyAll();
        }
    }
    ...
}

class DoStuffToListListWorker extends SwingWorker<Foo,Bar>
{
    ...
    protected Foo doInBackground()
    {
        synchronized (listYouveBeenFilling)
        {
            while (!listIsFull)
            {
                try
                {
                    listYouveBeenFilling.wait();
                }
                catch (InterruptedException ie)
                {
                    // Don't worry, we'll just wait again
                }
            }
        }
    }
    ...
}

其他提示

  

我如何告诉第二个进程等到第一个是做了什么?我想我可以只窝在第一个结束的第二个过程,但我不知道,这似乎是不好的做法。

您看着使用可调用及期货呢?他们听起来像一个很好的匹配这样的事情(让一个上的Future.get(在doStuffToList工作),而不是实际的列表,所以当得到的是把它叫做会做好准备),除了整体的SwingWorker业务。(认为这是一个建议,而不是一个答案)

我们有这样的事情:

private SwingWorkerExecutor swingWorkerExecutor;

//...

protected void runChain(List<SwingWorker<Void>> chainWorkers,
                        final SwingWorkerExecutor.RunAfter<Void> runAfter,
                        final SwingWorkerExecutor.RunOnError runOnError)
{
    final List<SwingWorker<Void>> remainingWorkers =
        chainWorkers.subList(1, chainWorkers.size());
    SwingWorkerExecutor.RunAfter<Void> chainRunAfter;
    if (chainWorkers.size() > 1)
    {
        chainRunAfter = new SwingWorkerExecutor.RunAfter<Void>()
        {
            @Override
            public void run(Void value)
            {
                runChain(remainingWorkers, runAfter, runOnError);
            }
        };
    }
    else
    {
        chainRunAfter = runAfter;
    }

    currentWorker = chainWorkers.get(0);

    swingWorkerExecutor.execute(currentWorker, chainRunAfter, runOnError);
}

这是非常简单的,海事组织,因为在我们的例子中SwingWorkerExecutor实际上包含了所有的难以理解的东西:

public class DefaultSwingWorkerExecutor implements SwingWorkerExecutor
{
    @Override
    public <T> void execute(SwingWorker<T, ?> worker, RunAfter<T> after,
                            RunOnError onError)
    {
        worker.addPropertyChangeListener(
            new RunAfterHandler<T>(worker, after, onError));
        worker.execute();
    }

    private static class RunAfterHandler<T> implements PropertyChangeListener
    {
        private final SwingWorker<T, ?> worker;
        private final RunAfter<T> after;
        private final RunAfter<Throwable> onError;

        protected RunAfterHandler(SwingWorker<T, ?> worker, RunAfter<T> after,
                                  RunOnError onError)
        {
            this.worker = worker;
            this.after = after;
            this.onError = onError;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt)
        {
            if ("state".equals(evt.getPropertyName()) &&
                evt.getNewValue() == SwingWorker.StateValue.DONE)
            {
                if (worker.isCancelled())
                {
                    return;
                }

                try
                {
                    after.run(worker.get());
                }
                catch (InterruptedException e)
                {
                    Thread.currentThread().interrupt();
                }
                catch (ExecutionException e)
                {
                    onError.run(e);
                }
            }
        }
    }
}

有一些缺少的接口应该是相当直截了当,而不这里看到他们写的。

我们的实际部署SwingWorkerExecutor执行使用一个注入的ExecutorService而不是默认的(这减少了我们需要一个单一的应用程序的线程池的数量。)但是我们介绍SwingWorkerExecutor是它简化和标准化了的SwingWorker的处理的真正原因成功和错误条件,还允许更换逻辑单元测试(其中,因为我敢肯定你知道,是如果他们是单线程的。简单多了)正如你可以看到有一堆样板,你通常会需要的每一个SwingWorker类中完成的(),所以不是这样做,我们把()完成工作进入一个回调。

在侧面的好处是,事情就像一个链条运行多个摇摆工人变得很容易实现。

要依次执行两个过程,传统上你只需要调用一个方法后,其他(!)。

fillList();
doStuffToList();

或许是这样的:

doStuffToList(fillList());

如果你是在一次处理一个,你可能想两个线程之间用BlockingQueue。你可能会具有多个DO-东西线走的更远。

至于AWT事件指派线程(EDT)关注它只是剥离动作而不会阻塞,以后将被通报。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top