RenderableImageProducer 和线程安全

发布于 2024-10-15 05:45:26 字数 3426 浏览 1 评论 0原文

我一直遇到 RenderableImageProducer 的问题,我认为这是由于多线程造成的。基本上,如果我创建多个引用相同 RenderableImage 的 RenderableImageProducer,它们似乎会混合在一起,就好像它们正在共享某些状态一样。

有人可以看一下并告诉我我的代码中是否犯了错误(很有可能!)或者 JavaSE 库中是否存在错误?

我在下面发布了我的测试代码(通过剥离我的“真实”代码来实现),抱歉它有点长,但我不能让它更短。

package imagemangler;

import java.awt.Component;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderContext;
import java.awt.image.renderable.RenderableImage;
import java.awt.image.renderable.RenderableImageProducer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MyRenderableImage implements RenderableImage {
    /* Implement RenderableImage methods */

    public Vector<RenderableImage> getSources() {
        return null;
    }

    public Object getProperty(String name) {
        return java.awt.Image.UndefinedProperty;
    }

    public String[] getPropertyNames() {
        return null;
    }

    public boolean isDynamic() {
        return false;
    }

    public float getWidth() {
        return 256.0f;
    }

    public float getHeight() {
        return 256.0f;
    }

    public float getMinX() {
        return 0.0f;
    }

    public float getMinY() {
        return 0.0f;
    }


    public RenderedImage createDefaultRendering() {
        int width = 256;
        int height = 256;
        Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Creating render {0}x{1} on thread {2}", new Object[]{width, height, Thread.currentThread().getId()});
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        // Don't bother drawing anything
        return bi;
    }

    /* Create eight scaled copies; RenderableImageProducer will start a
     * thread for each
     */
    public static void main(String[] args) {
        // Create a dummy component.
        Component component = new Component() {
        };
        Image base = component.createImage(new RenderableImageProducer(new MyRenderableImage(), null));
        MediaTracker mt = new MediaTracker(component);
        for (int i = 0; i < 8; ++i) {
            int size = 1 << i;
            Image mipmap = base.getScaledInstance(size, size, Image.SCALE_SMOOTH);
            mt.addImage(mipmap, i);
        }
        try {
            mt.waitForAll(1000);
        } catch (InterruptedException ex) {
        }
    }

    public RenderedImage createScaledRendering(int w, int h, RenderingHints hints) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public RenderedImage createRendering(RenderContext renderContext) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

这给了我错误:

Exception in thread "RenderableImageProducer Thread" java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
at sun.awt.image.IntegerInterleavedRaster.setDataElements(IntegerInterleavedRaster.java:404)

我已经做了尽可能多的跟踪,但看不到我的代码中有什么问题。

如果我使用不同的图像作为“基础”,则 main() 函数可以正常工作,例如来自 component.getImage(String) 的图像,甚至是自定义的 ImageProducer。

因此我认为它一定是RenderableImageProducer中的东西。

我正在使用java版本“1.6.0_23” Java(TM) SE 运行时环境(版本 1.6.0_23-b05) Java HotSpot(TM) 客户端 VM(内部版本 19.0-b09,混合模式,共享) 在 WinXP、SP3 32 位上

I've been having a problem with RenderableImageProducer which I think is due to multi-threading. Basically if I create several RenderableImageProducers referencing the same RenderableImage they seem to get mixed up as if they are sharing some state.

Could someone have a look and tell me if I've made a mistake in my code (quite possible!) or if there's a bug in the JavaSE library?

I've posted my test code below (arrived at by stripping down my 'real' code), sorry it's a bit long but I can't make it any shorter.

package imagemangler;

import java.awt.Component;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderContext;
import java.awt.image.renderable.RenderableImage;
import java.awt.image.renderable.RenderableImageProducer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MyRenderableImage implements RenderableImage {
    /* Implement RenderableImage methods */

    public Vector<RenderableImage> getSources() {
        return null;
    }

    public Object getProperty(String name) {
        return java.awt.Image.UndefinedProperty;
    }

    public String[] getPropertyNames() {
        return null;
    }

    public boolean isDynamic() {
        return false;
    }

    public float getWidth() {
        return 256.0f;
    }

    public float getHeight() {
        return 256.0f;
    }

    public float getMinX() {
        return 0.0f;
    }

    public float getMinY() {
        return 0.0f;
    }


    public RenderedImage createDefaultRendering() {
        int width = 256;
        int height = 256;
        Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Creating render {0}x{1} on thread {2}", new Object[]{width, height, Thread.currentThread().getId()});
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        // Don't bother drawing anything
        return bi;
    }

    /* Create eight scaled copies; RenderableImageProducer will start a
     * thread for each
     */
    public static void main(String[] args) {
        // Create a dummy component.
        Component component = new Component() {
        };
        Image base = component.createImage(new RenderableImageProducer(new MyRenderableImage(), null));
        MediaTracker mt = new MediaTracker(component);
        for (int i = 0; i < 8; ++i) {
            int size = 1 << i;
            Image mipmap = base.getScaledInstance(size, size, Image.SCALE_SMOOTH);
            mt.addImage(mipmap, i);
        }
        try {
            mt.waitForAll(1000);
        } catch (InterruptedException ex) {
        }
    }

    public RenderedImage createScaledRendering(int w, int h, RenderingHints hints) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public RenderedImage createRendering(RenderContext renderContext) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

This gives me errors:

Exception in thread "RenderableImageProducer Thread" java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
at sun.awt.image.IntegerInterleavedRaster.setDataElements(IntegerInterleavedRaster.java:404)

I've done as much tracing as I can but can't see what's wrong in my code.

The main() function works fine if I use a different image for 'base', for example something from component.getImage(String), or even a custom ImageProducer.

Therefore I think it must be something in RenderableImageProducer.

I am using java version "1.6.0_23"
Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
Java HotSpot(TM) Client VM (build 19.0-b09, mixed mode, sharing)
on WinXP, SP3 32-bit

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文