为什么java多线程不会加速图形程序

时间:2014-01-31 23:41:14

标签: java multithreading graphics bufferedimage zbuffer

我正在尝试绘制一个没有多个线程的三角形,每个线程将绘制一个独立的三角形片段。但它的运行速度比仅使用一个线程慢得多。什么是问题?

这是代码:

    (...)
int nCores = Runtime.getRuntime().availableProcessors();
    Thread[] threads = new Thread[nCores];
    int width = box[1][0] - box[0][0];
    int incr = width / nCores;
    int x = box[0][0];
    for (int i = 0; i < nCores; i++) {
        threads[i] = new Thread(new TriFiller(x, x + incr, z - nx * incr
                * i));
        threads[i].start();
        x += incr;
    }
    try {
        for (int i = 0; i < nCores; i++)    
            threads[i].join();
    } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

和runnable:

public class TriFiller implements Runnable {
    int xi, xf;
    double z;

    public TriFiller(int xi, int xf, double z) {
        super();
        this.xi = xi;
        this.xf = xf;
        this.z = z;
    }

    @Override
    public void run() {
        boolean inOut = false;
        double z0 = z;
        int rgbColor = shade.getRGB();
        BufferedImage image = wd.getImage();
        for (int i = xi; i < xf; i++) {
            for (int j = box[0][1]; j < box[1][1]; j++) {
                if (isOnSet(i, j, polyNormals, intBuffer)
                        && z < zBuffer[i][j] && z > zd) {
                    image.setRGB(i, j, rgbColor);
                    zBuffer[i][j] = z;
                    inOut = true;
                } else {
                    if (inOut) {
                        break;
                    }
                }
                z += -ny;
            }
            z0 += -nx;
            z = z0;
            inOut = false;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你遇到麻烦的原因是,摇摆画不适用于多线程。从另一个forum (jfree.org)阅读此摘录:

“我认为你没有看到任何性能提升的原因是你没有通过剥离另一个线程来引入任何并行性。

在Swing中更新屏幕的方式基本上是:

1)一旦组件决定它应该在屏幕上重新绘制,就会调用JComponent.repaint()。这导致异步重绘请求被发送到RepaintManager,它使用invokeLater()在EDT上对Runnable进行排队。

2)当Runnable执行时,它会调用RepaintManager,它会调用Component上的paintImmediately()。然后该组件设置剪辑矩形并调用paint(),最终调用您已重写的paintComponent()。请记住,屏幕已锁定,并且在组件完全重新绘制脏矩形之前将保持锁定状态。

旋转线程生成图像缓冲区是没有意义的,因为RepaintManager必须阻塞,直到缓冲区准备就绪,这样它才能在释放屏幕上的锁之前完成更新脏矩形。

swing支持的所有工具包(windows,linux,mac)都是单线程设计。无法同时更新屏幕的多个区域。“