优化:绘画同步

时间:2013-04-30 20:57:02

标签: java multithreading synchronization paint

我在绘画方面遇到了一些沉重的优化问题。我的代码示例如下所示:

BufferedImage img1;
synchronized(game.players){
    synchronized(game.monsters){
        synchronized(game.playersHealth){
            synchronized(game.monstersHealth){
                synchronized(game.overlays){
                    synchronized(game.projectiles){
                        img1 = game.drawAll();
                    }
                }
            }
        }
    }
}
game.setImage(img1);
game.repaint();

我知道这对你们大多数人来说可能很可怕。问题是,我有多组不同的对象包含数据(玩家,怪物等),这个代码块^在一个单独的线程上的“无限”循环中运行,组织所有图像,然后告诉游戏再次画自己。我需要帮助。你们能指出我正确的方向做正确的事吗?

1 个答案:

答案 0 :(得分:1)

请注意synchronized关键字:它仅用于提供对给定对象上的锁的独占访问权限。如果没有其他代码段尝试在同一个锁上进行同步,则只有执行该特定代码段的线程才会同步

这意味着:

  • 您的其他主题必须为操作该集合中的一个或多个元素的语句锁定任何这些集合。
  • 锁定的唯一内容是集合:如果T在同步块之外,则在执行同步代码时,持有对元素的引用的线程T仍然可以同时修改它到渲染线程R。

现在,关于您的代码,一种解决方案是通过锁定单个对象在渲染功能中推送同步。您可能在每个集合上都有一个循环,它逐个处理元素,或者说是某种效果:这可能是您想要进行同步工作的地方,也可能是元素本身。例如,您可以通过让每个游戏实体实现两个接口:渲染和逻辑,让渲染线程只访问渲染界面,逻辑游戏访问逻辑界面,将游戏逻辑从游戏渲染中分离出来。

通过将特定接口中的两个问题分开,您可能能够更好地区分哪些信息被哪些信息使用,哪些信息需要正确同步。

另一个解决方案,可能涉及更少的重构,包括将逻辑和渲染线程转换为生产者消费者设置:每个线程通过实体列表工作,当完成一个时,将其推送到另一个线程队列。每个实体都将在线程之间来回移动,让线程在它们上工作,而不需要任何其他形式的同步,而不是它们各自的输入队列。

如果你对每个线程有不同的排序约束,那么除了尝试重新组合依赖关系组中的实体,然后批量处理它们(线程处理批处理,并将该批处理作为单项到另一个线程队列),即。尝试分离不相互依赖的实体。