【问题标题】:Always the same thread gets CPU time总是同一个线程获得 CPU 时间
【发布时间】:2013-08-22 04:10:33
【问题描述】:

代码太大了,我只复制有问题的部分。

这是一个类中的 run() 方法:

public void run(){
try{
    sleep(1000);
    while(true){
          synchronized(space){

        if(end)
          return;

        if(space[X][Y] == null)
          break;

        if(((Ship)space[X][Y]).isDestroyed){
          destroy();
          break;
        }

        if(isThereAnyShipsInTheArea() != 0){
          if(team != ((Ship)space[X][Y + isThereAnyShipsInTheArea()]).team){
            fight(isThereAnyShipsInTheArea());
          }
        }
        else
          move();

        if(isDestroyed){
          destroy();
          break;
        }
    }
    }
}
catch(InterruptedException ie){
  System.out.println("Interrupted exception!");
}

}

这是星际迷航的模拟。可变团队表示该船属于哪个团队。如果船在战斗中被摧毁或在移动时坠毁,则变量 isDestroyed 为真。 isThereAnyShipsInTheArea() - 如果距离一到二,船就在范围内。 空间是维度为 [90]x[90] 的矩阵。

我认为问题在于运行方法,但我会给你一些其他方法。

    private int isThereAnyShipsInTheArea(){
  if(space[X][Y - 2] instanceof Ship && ((Ship)space[X][Y - 2]).isDestroyed == false)
    return -2;

  if(space[X][Y - 1] instanceof Ship && ((Ship)space[X][Y - 1]).isDestroyed == false)
    return -1;

  if(space[X][Y + 1] instanceof Ship && ((Ship)space[X][Y + 1]).isDestroyed == false)
    return 1;

  if(space[X][Y + 2] instanceof Ship && ((Ship)space[X][Y + 2]).isDestroyed == false)
    return 2;

  return 0;

}

 private synchronized void fight(int meet){


  while(((Ship)svemir[X][Y]).isDestroyed == false && ((Ship)space[X][Y + meet]).isDestroyed == false){
    if(((Ship)space[X][Y]).getProjectile() != 0){
      ((Ship)space[X][Y + meet]).setShield(((Ship)space[X][Y + meet]).getShield() - 1);
      ((Ship)space[X][Y + meet]).setWarp(((Ship)space[X][Y + meet]).getWarp() - 1);
      ((Ship)space[X][Y]).setProjectile(((Ship)space[X][Y]).getProjectile() - 1);

      if(((Ship)space[X][Y + meet]).getShield() == 0 || ((Ship)space[X][Y + meet]).getWarp() == 0){
        ((Ship)space[X][Y + meet]).isDestroyed = true;
        return;
      }
    }

    if(((Ship)space[X][Y + meet]).getProjectile() != 0){
      ((Ship)space[X][Y]).setShield(((Ship)space[X][Y]).getShield() - 1);
      ((Ship)space[X][Y]).setWarp(((Ship)space[X][Y]).getWarp() - 1);
      ((Ship)space[X][Y + meet]).setProjectile(((Ship)space[X][Y + meet]).getProjectile() - 1);

      if(((Ship)space[X][Y]).getShield() == 0 || ((Ship)space[X][Y]).getWarp() == 0){
        this.isDestroyed = true;
        return;
      }

    }

    if(((Ship)space[X][Y]).getProjectile() == 0 && ((Ship)space[X][Y + meet]).getProjectile() == 0)
      return;

  }

}

【问题讨论】:

  • 您应该在 run 方法的循环中使用 Thread.yieldThread.sleep,但在 synchronized 块之外...
  • 一段时间后,同一个线程总是得到时间,虽然还有其他正在运行的线程
  • 如果你想要这样的模拟,你最好使用一个线程。如果您使用多个线程,锁定和同步的开销可能意味着您的程序速度较慢,而且如您所见,当然更难以预测。如果您使用一个线程,您可以准确地看到处理顺序。

标签: java multithreading synchronization


【解决方案1】:

对我来说,您不应该执行 Thread.sleep(),因为它不会释放它获取的任何资源。要么使用 ScheduledExecutorService 安排您的任务,要么在对象监视器上执行 wait() 和 yield()。

【讨论】:

    【解决方案2】:

    你的睡眠在你的while(true) 块之外,所以不是每个循环都睡一秒钟,而是睡一次,然后进入一个紧密的循环。

    将 sleep 放在 while(true) 块的末尾,这样每次循环迭代都会休眠一次。理想情况下,它应该是在空间数组上的同步释放之后。

    实际上,全阵列扫描在查找项目方面远非理想。可能想考虑保留项目列表。想一想,一个 1000x1000 的数组,其中有 20 个项目(空间很大,而且大部分是空的),当您通过数组时将进行 1,000,000 次检查,但是如果您根据项目重新组织检查,您可能会只需 1000 次或更少的支票就可以逍遥法外。

    例如,船舶列表:

    for (Ship ship : ships) {
       if (!ship.engaged()) {
         ship.scanForEnemies();
       }
       if (ship.detectEnemies()) {
         ship.attack();
       }
    }
    

    可能只需要遍历十几艘或更少的船只,检查几百个位置。如果你想知道上面的代码是如何工作的,在我的例子中,船应该是用一个空间数组构造的,它保留了一个引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-14
      • 2014-12-08
      • 2012-03-16
      • 2021-02-23
      • 2011-08-29
      相关资源
      最近更新 更多