当前位置: 首页 > 知识库问答 >
问题:

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

孟鸿朗
2023-03-14

各位。我正在为一个编程课做一个游戏,由两条蛇组成,它们朝相反的方向走在一条边界上。它们需要阻挡障碍物,我使用协调使它们不会相互对抗。这意味着第二个尝试访问细胞,需要等到第一个解锁细胞。我已经在这个网站上阅读了很多主题,但我仍然没有找到解决问题的方法。

现在我已经看到蛇在板上四处移动,并在障碍物中阻塞。下面是我的两大问题,我非常感谢您的帮助:

1-有特定的情况,例如,两条蛇走paralell,当他们试图把方向转向另一条蛇他们都阻止和游戏停止在那里,造成死锁。只有一个可以停止,而另一个等待第一个解除屏蔽单元格。我stil没有找到解决方案的具体问题。如果他们不碰撞在每一个的方向,没有问题。一条蛇等待另一个清除cel...我已经在这里读到一个关于使用CountDownLatch的解决方案,但不知道如何实现它。

2.当蛇在障碍物中受阻时,继续等待()。然后,我让她在黑板上的一个单元格中再次移动,蛇需要重新计算一种新的方式才能进入我点击的单元格。这意味着我需要将运动从随机变为特定。老师让我们打断线程,让她离开她正在做的方法(moveNextCell()),然后重新计算下一个动作。这里的问题是,我可以处理中断,但不知道如何再次激活线程。我读了它,不知道我是否理解得不好,在一个线程被中断后,我无法再次启动它,所以我需要复制它。但现在我不知道如何在代码中实现,因为新线程需要蛇的实际位置、颜色等。

现在我不能同时做这两种情况。

单元格代码(在遇到障碍或一条蛇想使用另一个单元格时,可以阻止蛇)如下所示:

公共同步的无效保留Cell(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 ;
   }

snake代码(使其移动)如下所示:

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个答案

方祺
2023-03-14

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

正如班塔尔所说,问题是蛇不知道其他的蛇。这意味着在这两种特定的情况下,它们会互相阻挡,等待对方移动=

这里的解决方案是,其中一个警告另一个:“嘿,斯内克,我被挡了。不要挡着等我,否则我们都会被卡住。”。

在互联网上搜索时,我发现了许多使用线程池的解决方案,这些解决方案可以协调所有这些解决方案,但这对我的问题来说太难了。

所以我在《蛇》中做了一个致敬,叫做蛇阻断,当蛇阻断时就变成了真的。当蛇试图接近它时,在细胞中进行操作。所以当第二条蛇试图与一条蛇接触一个细胞时,细胞有一个方法来找出被困在细胞中的蛇的蛇阻断值是多少。之后变得很容易。

如果想进入牢房的蛇知道那里有条被堵住的蛇,她会改变方向。

希望它能帮助一些人,因为我被困在这些很长一段时间。

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

穆宾白
2023-03-14

班瑟,我刚刚尝试了你的第二个解决方案,效果很好!我从来没有想过这些,所有这些例外的事情对我来说真的是一件新鲜事!

像以前一样,我要说我为了帮助别人做了什么。

正如班瑟所说,我使用的所有方法都会导致中断,我把它们放到蛇的运行中。这样我就可以停止线程并制作一个新线程。然后我添加了一个方法来改变方向,像banthar put那样重新开始。

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

薛修能
2023-03-14

您对此无能为力。如果蛇是独立的线程,它们彼此不知道,并且无法自己解决冲突。您的教授应该指定如何解决此类死锁。最简单的解决方案是保持蛇死锁,直到用户交互并选择不同的目标。您还可以将超时添加到wait()方法。如果一段时间后单元格不可用,请随机选择不同的方向。

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

>

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();

您还可以更改目标并仅中断main方法:

@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();
 类似资料:
  • 由于使用stop()方法停止线程非常的暴力,人家线程运行的好好的,突然就把人家杀死了,线程占用的锁被强制释放,极易导致数据的不一致性。因此,提出了一种温和的方式:请求另外一个线程不要再执行了,这就是中断方式。 假设某个线程要不停地处理某件事情(比如 i 一直自增),但是还有个要求:在处理事情前,先要检查下这个线程是否被中断,如果已经被中断,处理就应该结束。 public class Run {

  • 死锁描述了两个或多个线程永远被阻塞,等待彼此的情况。 当多个线程需要相同的锁但以不同的顺序获取它们时,会发生死锁。 Java多线程程序可能会遇到死锁条件,因为synchronized关键字会导致执行线程在等待与指定对象关联的锁定或监视器时阻塞。 这是一个例子。 例子 (Example) public class TestThread { public static Object Lock1

  • 在 linux 内核中你会发现很多关于中断和异常处理的话题 中断和中断处理 Part 1. - 描述中断处理主题 深入 Linux 内核中的中断 - 这部分开始描述和初步步骤相关的中断和异常处理。 初步中断处理 - 描述初步中断处理。 中断处理 - fourth part describes first non-early interrupt handlers. 异常处理的实现 - 一些异常处理的

  • 本文向大家介绍Android中断线程的处理方法,包括了Android中断线程的处理方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android中断线程的处理方法。分享给大家供大家参考。具体方法如下: 我现在对一个用户注册的功能 1.用ProgressDialog将当前页面设成不可操作(保留返回键 退出ProgressDialog) 2.用一个线程clientThread执行数据的提交

  • 终结篇 本文是 Linux 内核中断和中断处理的第十节。在上一节,我们了解了延后中断及其相关概念,如 softirq,tasklet,workqueue。本节我们继续深入这个主题,现在是见识真正的硬件驱动的时候了。 以 StringARM** SA-100/21285 评估板串行驱动为例,我们来观察驱动程序如何请求一个 IRQ 线,一个中断被触发时会发生什么之类的。驱动程序代码位于 drivers

  • 延后中断(软中断,Tasklets 和工作队列)介绍 这是 Linux 内核中断和中断处理的第九节,在上一节我们分析了源文件 arch/x86/kernel/irqinit.c 中的 init_IRQ 实现。接下来的这一节我们将继续深入学习外部硬件中断的初始化。 中断处理会有一些特点,其中最主要的两个是: 中断处理必须快速执行完毕 有时中断处理必须做很多冗长的事情 就像你所想到的,我们几乎不可能同