繁体   English   中英

猜测同时运行的线程的下一个位置

[英]Guess the next position of simultaneously running threads

我正在制作一个迷宫,两条线正在同时进行。问题是它们不能同时共享同一个位置。 我不知道该怎么办。 是否有可能知道它们下一步将移动到哪里并阻止另一根线程移动到该位置? 请给我一个主意。 谢谢。

这里的代码:

        public int[][] visitedCell=new int[15][15]; // holds how many times visited for each cell
    public boolean cntrl=true,repeat=true,end;
    public int r=0;
    public int cnt;
    public boolean find;
    public void  decision(int posX,int posY){
       int distanceToExit;
       cnt=0; // holds how many cell is free around the cell which thread is on
       r=0;
       end=false; // checks robot found exit
       find=false; // checks suitable cell found to move in next step
       posX=posX/40; // all cells are 40*40 dimension.since it is divided 40 to find poisition
       posY=posY/40; // found y position
       int[][] neighbours={{posX,posY+1},{posX+1,posY+1},{posX+1,posY},{posX+1,posY-1},{posX,posY-1},{posX-1,posY-1},{posX-1,posY},{posX-1,posY+1}}; // all 8 neighbours of a cell
       int[][] freeCellChoises = new int[8][2]; // holds free cells to move
       int[][] distanceCell=new int[8][2];
       for(int i=0;i<8;i++){ // checks which neighbour cells are free
             if((neighbours[i][0] >0 && neighbours[i][0] <14) && (neighbours[i][1] >0 && neighbours[i][1] < 14) || (neighbours[i][0]==1 && neighbours[i][1]==14) || (neighbours[i][0]==14 && neighbours[i][1]==1) ) // [1,14] = enter position and [14,1]= exit position
             {
               if(Draw.paintArray[neighbours[i][0]][neighbours[i][1]]==0){// cell is free.it is eligible
                   freeCellChoises[cnt][0]=neighbours[i][0]; // load eligible cells this array
                   freeCellChoises[cnt][1]=neighbours[i][1];
                   distanceToExit=(int) Math.sqrt((Math.pow(neighbours[i][0]-560, 2)+Math.pow(neighbours[i][1]-40,2)));
                   distanceCell[cnt][0]=cnt;
                   distanceCell[cnt][1]=distanceToExit;
                   cnt++;}
             }
       } // eligible cells are ready anymore
       if(Frame.radButSel==1){ // random movement
           int no=rndm.nextInt(cnt); // choose one of the eligible cell randomly
           x=freeCellChoises[no][0] * 40;
           y=freeCellChoises[no][1] * 40;
       }
       if(Frame.radButSel==2){ // closed way movement ( find the most clodes cell to the exit ) .Exit is [14,1].So x must be max, y must be min to a cell has priority
           int maxX=freeCellChoises[0][0];
           int minY=freeCellChoises[0][1];
           int selection1=0,selection2=0;
           for(int i=0;i<cnt;i++){ // x i byk y si kck  sec
               if(freeCellChoises[i][0]> maxX){
                   maxX=freeCellChoises[i][0];
                   selection1=i;}
               if(freeCellChoises[i][1]<minY){
                   minY=freeCellChoises[i][1];
                   selection2=i;
               }


           }
         if(cnt!=0) // checks there is a priority cell
             r=rndm.nextInt(2)+1; // selects one of the priority cell

         if(r==1 && visitedCell[freeCellChoises[selection1][0]][freeCellChoises[selection1][1]] <2){ //selection1.same cell musnt be visited more than 2 times
               x=freeCellChoises[selection1][0] * 40;
               y=freeCellChoises[selection1][1] * 40;}

         else if(r==2 && visitedCell[freeCellChoises[selection2][0]][freeCellChoises[selection2][1]] <2){//selection2
              x=freeCellChoises[selection2][0] * 40;
              y=freeCellChoises[selection2][1] * 40;}

          else{ // applies when there is not any priority cell
               System.out.println("oncelik yok");
               int repeat =0;
               while(repeat<cnt){
                  r=rndm.nextInt(cnt); // choose one of the eligible cell
                  x=freeCellChoises[r][0] * 40;
                  y=freeCellChoises[r][1] * 40;
                  if(visitedCell[freeCellChoises[r][0]][freeCellChoises[r][1]] <2){
                      repeat=10;
                  }
                  else
                      repeat++;

               }System.out.println("x="+x+"y="+y);

          }
      }
      if(Frame.radButSel==3){

      }

      if(x==560 && y==40){ // checks decided cell is exit point
           Action.pool.shutdownNow();// thread finished
           end=true;
           Main.butAct++; // when butAct=2 , "RESULT" button will be active
           timer.stopTime();} // stops time for the thread

      distance=(int) Math.sqrt(Math.pow(x-560,2) + Math.pow(y-40, 2));// calculates distance between thread - exit

}

public Action() throws InterruptedException{
    pool=Executors.newFixedThreadPool(2); // two thread in the pool
    robot1=new Robot(40,560); // starts enter position
    robot2=new Robot(40,560); // starts enter position
    pool.submit(robot1); // loads robot1 to pool
    pool.submit(robot2);// loadss robot2 to pool
}
public void run() {
    while(true){ // run threads always
    try {
        Frame.worker.pauseIfNeeded();} // checks whether pause button is pressed
    catch (InterruptedException ex) {
        Logger.getLogger(Robot.class.getName()).log(Level.SEVERE, null, ex);}
    if(end==false){// not reach exit
       try{
            System.out.println(Thread.currentThread().getName());// displays current thread name
            System.out.println("pozisyon x="+x+"y="+y);
            decision(x,y); // thread makes decision to move
            visitedCell[x/40][y/40]+=1; // increade number of visitide cell count for that cell in the array
            visCell++; //increase visited cell count for the thread
            Thread.sleep(300);} // thread sleeps for a while to observe movement changing
       catch(Exception ex){
       }
    }
    else{// found exit
            Thread.currentThread().interrupt(); // Thread killed
            if(Main.butAct==2)// after a thread found exit, checks if result button can be active anymore
               Frame.button4.setEnabled(true); // activates result button
    }
  }//end while

}

最简单的解决方案是以两种工作区域(要尝试的解决方案/路径)互斥的方式“划分”工作。 一种解决方法是拥有一组并发的位置,并在移动之前由每个线程检查这些位置。

您将不得不使用所谓互斥的概念。 在Java编程语言中,您将必须使用synchronized关键字为您完成这项工作。 在[1]中可以看到一个简单的例子:


public class SynchronizedCounter {
  private int i = 0;

  public synchronized void increment() {
    i++;
  }

  public synchronized void decrement() {
    i--;
  }

  public synchronized int value() {
    return i;
  }
}

在这里,您可以看到一个代码,确保只有一个线程能够修改共享变量i的值。 请注意,代码this用作所谓的“锁定对象”。 您可以通过以下方式重写代码:


public class SynchronizedCounter {
  private int i = 0;

  public void increment() {
    synchronized(this) {
      i++;
    }
  }

  public void decrement() {
    synchronized(this) {
      i--;
    }
  }

  public int value() {
    synchronized(this) {
      return i;
    }
  }
}

或者您可能想要创建自己的锁定对象并使用它:


public class SynchronizedCounter {
  private int i = 0;
  private Object lock = new Object();

  public void increment() {
    synchronized(lock) {
      i++;
    }
  }

  public void decrement() {
    synchronized(lock) {
      i--;
    }
  }

  public int value() {
    synchronized(lock) {
      return i;
    }
  }
}

现在,任意数量的线程都可以随机调用此对象的方法,但是一次只能有一个线程能够传递锁并进行实际的修改。

[1] http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

或者,您可以这样做。 管理器类知道两个线程的位置,并且moveTo方法检查它们在同一位置是否不一致。

class MazeManager {
  int x1, x2, y1, y2;

  public synchronized boolean moveTo(int threadId, int x, int y) {
    ..
  }
}

让管理迷宫的类强制线程通过自身进行同步,并发出更改其位置的请求。 然后,迷宫管理器可以基于其他线程的位置允许或拒绝移动请求。

像Sanjay说的那样,预防胜于治疗。 您可以对两个机器人遍历的单元进行分区,使它们永远不会共享同一个单元。 如果不可能,则解决方法是对每个单元使用锁。 机器人在进入单元之前会获得相应的锁,并在完成后释放锁。 如果机器人试图进入与另一个机器人相同的单元格,这将导致机器人等待。 与让迷宫管理者控制移动相比,这是一种更加分散的方法,将减少争用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM