【问题标题】:SnakeGame: How to deal with a interrupt thread and with a deadlockSnakeGame:如何处理中断线程和死锁
【发布时间】:2014-12-07 13:39:28
【问题描述】:

每个人。我正在为一个编程课程做一个游戏,该课程由两条沿相反方向行走的蛇组成。他们需要阻止 障碍,我使用协调使他们不会相互对抗。这意味着第二个尝试访问单元的人将需要等到第一个解除对单元的阻塞。我已经在这个网站上阅读了很多主题,但我仍然没有找到解决问题的方法。

现在我已经让蛇在棋盘周围移动并挡住了障碍物。我感谢任何帮助的两个大问题如下:

1- 有特定的情况,例如,两条蛇平行行走,当它们试图将方向转向另一条蛇时,它们都会阻挡并游戏 停在那里,导致死锁。只有一个可以停止,而另一个等待第一个解锁单元格。我仍然没有找到特定问题的解决方案。如果它们不碰撞 在每一个的方向上,都没有问题。一条蛇等待另一条清除细胞。我已经在这里阅读了有关使用 CountDownLatch 的解决方案,但不知道如何实现它。

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

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

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

公共同步无效reserveCell(Snake snakeID){ 这个 .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 ;
   }

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

公共无效运行(){ while(!Thread.currentThread().isInterrupted()){ moveNextCell(currentX, currentY); // 询问下一个单元格,如果可能,将单元格添加到蛇的主体并更新 GUI 设置随机方向(); // 定义下一步移动的方向。

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

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

   }

如果能帮助我在工作中取得进步,我将不胜感激。感谢您的帮助!

【问题讨论】:

  • 使用线程是您要求的一部分吗?看起来它作为一个单线程程序会简单得多。
  • Banthar,首先感谢您的帮助。不幸的是,它是一个协调和同步类,所以它们迫使我们使用多个线程!

标签: java multithreading deadlock


【解决方案1】:

我假设您在第 1 点中提到的情况如下所示:

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

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

  1. 您可以完全停止线程,然后使用新的目的地启动新线程。您必须从所有捕获中删除 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();
    
  2. 您也可以更改目的地并仅中断 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();
    

【讨论】:

  • Banthar,非常感谢您的帮助!关于第一个问题,就是这样!只是在他们阻止的那些情况下!我将尝试等待()的超时,并要求我的老师更具体地了解问题的解决方案。关于第二个问题,我现在要尝试该解决方案!在我反馈之后。 :) 再次感谢您!
【解决方案2】:

banthar,我刚刚尝试了您的第二个解决方案,效果很好!我从来没有想过这个,所有这些例外的东西对我来说真的是一个新事物!

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

正如班塔尔所说,我使用的所有方法都会导致中断,我把它们放到了蛇的 run() 中。所以这样我就可以停止线程并创建一个新线程。然后我只是添加使用一种方法来改变方向并像banthar put一样重新开始。

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

【讨论】:

    【解决方案3】:

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

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

    这里的解决方案是其中一个警告另一个“嘿 Snake,我被阻止了。不要阻止等待我,否则我们都会被卡住”。

    在互联网上搜索我发现了很多使用 ThreadPool 的解决方案,它们可以协调所有这些,但这对我的问题来说太多了。

    所以我在 Snake 中创建了一个名为snakeBlocked 的属性,当蛇阻塞时它变为真。当蛇试图访问它时,该操作在 Cell 中进行。因此,当第二条蛇试图用蛇访问一个单元格时,该单元格有一种方法可以找出卡在该单元格中的蛇的 snakeBlocked 值是多少。之后就很容易了。

    如果想要进入牢房的蛇知道那里有一条被阻塞的蛇,它就会改变方向。

    希望它可以帮助某人,因为我被困了很长时间。

    关于第2个问题,现在就试试,等我来了,如果我能找到解决办法!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      相关资源
      最近更新 更多