SnakeGame:如何处理中断线程和死锁

大家 . 我正在为一个编程课做一个游戏,这个编程课包含两条相反方向的b蛇 . 他们需要阻挡障碍,我使用协调来不相互对抗 . 这意味着第二个尝试访问一个单元,需要等到第一个解锁单元 . 我已经在这个网站上阅读了很多主题,但我仍然没有找到解决问题的方法 .

现在我已经让蛇全都四处移动并阻挡了障碍物 . 我的两大问题是,我感谢任何帮助,如下:

1-有特定的情况,例如,两条蛇走路并列,当他们试图将方向转向另一条蛇时,它们都会阻挡并且游戏停在那里,导致死锁 . 只有一个可以停止,而另一个等待第一个解锁单元格 . 我找不到具体问题的解决方案 . 如果它们没有朝每个方向发生碰撞,那就没问题了 . 一条蛇等待另一条蛇清除cel ..我已经在这里读到了一个关于使用CountDownLatch但不知道如何实现它的解决方案 .

2当蛇在障碍物中阻挡时,继续等待() . 然后我让她的动作再次蜷缩在董事会的一个牢房中,蛇需要重新计算一个新的方式去我爬到的牢房 . 这意味着我需要将运动从随机变为特定运动 . 老师说我们打断线程,让她离开她正在做的方法(moveNextCell())并再次重新计算下一个动作 . 这里的问题是我可以处理中断但不知道如何再次激活线程 . 我读了它,并且不知道我是否解释它是坏的,在线程中断之后,我无法再次启动它,所以我需要复制它 . 但是现在我不知道我怎么能在我的代码中做到这一点,因为新线程需要蛇的实际位置,颜色等 .

现在我无法做到这两种情况 .

单元格代码(在屏障情况下阻止蛇或一条蛇想要使用另一个单元格)如下:

public synchronized void reserveCell(Snake snakeID){this .snakeID = snakeID;

while (type .equals("Barrier" )){
                  try {
                       wait();
                 } catch (InterruptedException e ) {
                        // When snake it's blocked and we interrupt it, comes to this part!
                       Thread. currentThread().interrupt();
                        snakeID.doSpecificMovement();


                 }
          }
           while (inUse ){
                  try {
                       wait();
                 } catch (InterruptedException e ) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                 }
          }

          setSnakeID( snakeID);
           inUse = true ;
   }

蛇代码(使其移动)如下:

public void run(){while(!Thread.currentThread() . isInterrupted()){moveNextCell(currentX,currentY); //询问下一个单元格,如果可能的话将单元格添加到snake的主体并更新GUI setRandomDirection(); //定义下一步的方向 .

try {
                        sleep(gameSpeed);
                 } catch (InterruptedException e ) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                 }

                 gameOver(); // when the snakes reachs the end of the board finishs
          }

   }

我将不胜感激任何可以帮助我在工作中取得进步的帮助 . 谢谢你的帮助!

回答(3)

3 years ago

我假设你在第1点提到的情况看起来像这样:
deadlocking snakes

你无能为力 . 如果蛇是单独的线程,它们彼此不了解,也不能自己解决冲突 . 您的教授应指定如何解决此类死锁 . 最简单的解决方案是让蛇保持僵局,直到用户进行交互并选择不同的目的地 . 您还可以向 wait() 方法添加超时 . 如果细胞在一段时间后不可用,则随机选择不同的方向 .

有两种方法可以解决第二个问题:

  • 您可以完全停止线程,然后使用新目标启动新线程 . 您必须从所有捕获中删除 InterruptedException 并将其传播到 run() 方法:
void goToDestination() throws InterruptedException {
    ...
}

@Override
public void run() {
    try {
        goToDestination();
    } catch(InterruptedException e) {
        // end thread
        return;
    }
}

这样 interrupt() 将能够停止该线程 . 您可以像这样重新启动它:

// interrupt and wait until thread actually finishes
snake.thread.interrupt();
snake.thread.join();

// change the destination
snake.destination = newDestination;

// restart the thread
snake.thread = new Thread(snake);
snake.thread.start();
  • 您还可以更改目标并仅中断主方法:
@Override
public void run() {
    while(true) {
        try {
            goToDestination(destination);
        } catch (InterruptedException e) {
            // try again with changed destination
        }
    }
}

当用户选择新目的地时:

// set new destination
snake.destination = newDestination;

// interrupt old goToDestination
snake.thread.interrupt();

3 years ago

banthar,我刚尝试了你的第二个解决方案并且工作得很好!我从来没有想过这个,所有这些例外情况对我来说真的是一件新事!

像以前一样,我会说我做了什么以帮助其他人 .

正如banthar所说,我使用的所有方法都会导致中断,我将它们放到蛇的run()中 . 所以这种方式我能够阻止线程并创建一个新线程 . 然后我只是添加使用方法来改变方向,并像banthar put一样重新开始 .

问题解决了,非常感谢,希望这可以帮助更多的人!

3 years ago

关于第一期,我已经解决了 . 如果有人发现这对他们的问题有用,我会发布我的解决方案 .

正如班塔尔所说,问题在于蛇并不知道其他的蛇 . 这意味着在这两种情况下,它们会相互阻塞,等待对方移动=>死锁 .

这里的解决方案是让其中一人警告另一个人“嘿蛇,我被封锁了 . 不要阻止等我,否则我们都会被困住” .

在互联网上搜索我发现很多使用ThreadPool的解决方案可以协调所有这些解决方案,但这对我的问题来说非常重要 .

所以我在Snake中做了一个名为snakeBlocked的atrribute,当蛇阻塞时它变成了真实 . 操作是在细胞当蛇试图接近它时 . 因此当第二条蛇试图接近一条带蛇的细胞时,细胞有一种方法可以找出蛇被困在细胞中的蛇的 Value . 结果很简单 .

如果想要接近细胞的蛇知道那里有一条阻塞的蛇,她会改变方向 .

希望它可以帮助某人,因为我被困在那些很长一段时间 .

关于问题#2现在尝试一下,我来到这里后,如果我能找到解决方案!