gpt4 book ai didi

java - 如何阻止一个线程修改另一个线程正在使用的数组?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:25:18 25 4
gpt4 key购买 nike

我有一个 java 程序,它基本上是一个游戏。它有一个名为'World' 的类。 “World”类有一个方法 'levelChanger()' 和另一个方法 'makeColorArray()'

public class World {

private BufferedImage map, map1, map2, map3;
private Color[][] colorArray;

public World(int scrWd, int scrHi) {
try {
map1 = ImageIO.read(new File("map1.png"));
map2 = ImageIO.read(new File("map2.png"));
map3 = ImageIO.read(new File("map3.png"));
} catch (IOException e) {
e.printStackTrace();
}
map = map1;

makeColorArray();
}

private void makeColorArray() {
colorArray = new Color[mapHi][mapWd]; // resetting the color-array
for(int i = 0; i < mapHi; i++) {
for(int j = 0; j < mapWd; j++) {
colorArray[i][j] = new Color(map.getRGB(j, i));
}
}
}

//color-array used by paint to paint the world
public void paint(Graphics2D g2d, float camX, float camY) {
for(int i = 0; i < mapHi; i++) {
for(int j = 0; j < mapWd; j++) {
if(colorArray[i][j].getRed() == 38 && colorArray[i][j].getGreen() == 127 && colorArray[i][j].getBlue() == 0) {
//draw Image 1
}
else if(colorArray[i][j].getRed() == 255 && colorArray[i][j].getGreen() == 0 && colorArray[i][j].getBlue() == 0) {
//draw Image 2
}
}
}
}

public void levelChanger(Player player, Enemies enemies) {
if(player.getRec().intersects(checkPoint[0])) {
map = map2;
//calls the color-array maker
makeColorArray();
}
else if(player.getRec().intersects(checkPoint[1])) {
map = map3;
makeColorArray();
}
}

public void update(Player player, Enemies enemies) {
levelChanger(player, enemies);
}
}

makeColorArray() 方法生成“颜色”类型的二维数组。此数组存储来自 PNG 图像的颜色对象。 JPanel 的 paint() 方法使用此数组在屏幕上绘制世界。

levelChanger() 方法用于在特定条件为真时更改游戏的级别(阶段)。它是在改变游戏关卡时调用makeColorArray()方法重新制作颜色数组的方法。

问题是我有一个在线程上运行的游戏循环。现在,像 JPanel 这样的 swing 组件的绘制是由 java 在不同的后台线程上完成的。当改变游戏关卡时,重新创建颜色数组对象。现在,正如我之前所说,颜色数组对象被 paint() 方法用于在屏幕上绘制世界。有时,根据游戏逻辑重新制作颜色数组对象并将其成员设置为空时,颜色数组对象仍在被后台线程(未完成绘制)使用。这会导致空指针异常,只是有时会发生。显然是竞争条件。

我想知道如何阻止我的游戏线程在背景 Swing 线程完成绘制之前重置颜色数组。

最佳答案

建议:

  • 为您的程序使用模型- View -控制设计,或使用许多类似变体中的一种。
  • 使用 Swing 计时器来驱动您的 GUI 游戏循环,但在您的模型中使用实时片段而不是计时器的延迟来确定循环步骤之间的时间长度。
  • 模型应该在 GUI Swing 事件线程中运行。
  • 但是它的长时间运行的任务应该使用 SwingWorker 在后台线程中运行。
  • 这是关键:不要更新模型的数据,即 JPanel 用来绘制的数据,直到后台线程完成对它的处理。 PropertyChangeListener 和 SwingPropertyChangeSupport 对此很有用。
  • 确保 JPanel 在它的 paintComponent(...) 方法中绘制,而不是它的 paint(...) 方法,并且你调用了 super 方法.
  • 最好将背景图像设为 BufferedImage,并让 JPanel 在其 paintComponent(...) 方法中绘制该图像以提高效率。
  • 确保在 Swing 事件线程上调用所有 Swing GUI 代码,也许 repaint() 调用除外。
  • 是的,一定要阅读 Concurrency in Swing tutorial .

关于java - 如何阻止一个线程修改另一个线程正在使用的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27573978/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com