Java 在不使事件调度线程等待的情况下渲染图像?

Java 在不使事件调度线程等待的情况下渲染图像?,java,multithreading,concurrency,event-dispatch-thread,Java,Multithreading,Concurrency,Event Dispatch Thread,我在多个线程上渲染一个BuffereImage。当我启动这些线程时,我正在调用事件调度线程上的wait,以便它仅在所有渲染线程都发送了notify信号时才实际绘制图像 这就是EDT中发生的情况: synchronized (this) { while(threadsCompleted<RENDERING_THREADS){ try{ this.wait(); }catch (Interr

我在多个线程上渲染一个BuffereImage。当我启动这些线程时,我正在调用事件调度线程上的wait,以便它仅在所有渲染线程都发送了notify信号时才实际绘制图像

这就是EDT中发生的情况:

synchronized (this)
    {
        while(threadsCompleted<RENDERING_THREADS){
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        threadsCompleted = 0;
    }
g2.drawImage(image);

我的问题是:有没有一种方法可以让对drawImage的调用等待线程完成,而不实际停止EDT工作?有没有一种方法可以让用户在渲染进行的毫秒内与UI进行交互,从而事件调度线程?

最简单的方法是使用
java.util.concurrent
中的并发结构,并使用等待所有其他线程完成的线程,如下所示:

public class ImageRenderer implements Runnable
{
    private final CountDownLatch latch;

    public ImageRenderer(CountDownLatch latch)
    {
        this.latch = latch;
    }

    @Override
    public void run()
    {
        try
        {
            // code...
        } finally
        {
            latch.countDown();
        }
    }
}

public class Waiter implements Runnable
{
    private final CountDownLatch latch;

    public Waiter(CountDownLatch latch)
    {
        this.latch = latch;
    }

    @Override
    public void run()
    {
        try
        {
            latch.await();
            // rendering has now finished.
            SwingUtilities.invokeLater(() -> {
                // do something with the image on the EDT
            }
        } catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
    }
}

将\第一个同步代码移动到它自己的线程中,并使用SwingUtilities invokeLater Runnable run方法调用drawImage方法。
public class ImageRenderer implements Runnable
{
    private final CountDownLatch latch;

    public ImageRenderer(CountDownLatch latch)
    {
        this.latch = latch;
    }

    @Override
    public void run()
    {
        try
        {
            // code...
        } finally
        {
            latch.countDown();
        }
    }
}

public class Waiter implements Runnable
{
    private final CountDownLatch latch;

    public Waiter(CountDownLatch latch)
    {
        this.latch = latch;
    }

    @Override
    public void run()
    {
        try
        {
            latch.await();
            // rendering has now finished.
            SwingUtilities.invokeLater(() -> {
                // do something with the image on the EDT
            }
        } catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
    }
}