简体   繁体   English

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

[英]Guess the next position of simultaneously running threads

I am making a maze and two threads are moving on it simultaneously.The problem they mustn't share the same position at same time. 我正在制作一个迷宫,两条线正在同时进行。问题是它们不能同时共享同一个位置。 I don't know how I can do it. 我不知道该怎么办。 Is it possible to know where they will move next and prevent the other thread from moving to that position? 是否有可能知道它们下一步将移动到哪里并阻止另一根线程移动到该位置? Please give me an idea. 请给我一个主意。 Thanks. 谢谢。

Here the code : 这里的代码:

        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

} }

The most simple solution would be to "divide" the work in such a way that the two work regions (solutions/paths to be tried out) are mutually exclusive. 最简单的解决方案是以两种工作区域(要尝试的解决方案/路径)互斥的方式“划分”工作。 A workaround would be to have a concurrent set of positions which would be checked by each thread before making a move. 一种解决方法是拥有一组并发的位置,并在移动之前由每个线程检查这些位置。

You will have to use the concept of so called mutual exclusion. 您将不得不使用所谓互斥的概念。 In the Java programming language, you will have to use the synchronized keyword to do the job for you. 在Java编程语言中,您将必须使用synchronized关键字为您完成这项工作。 A simple example maybe seen at [1]: 在[1]中可以看到一个简单的例子:


public class SynchronizedCounter {
  private int i = 0;

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

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

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

Here you see a code that makes sure that only one thread is able to modify the value of the shared variable i . 在这里,您可以看到一个代码,确保只有一个线程能够修改共享变量i的值。 Note that the code uses this as the so-called "lock object". 请注意,代码this用作所谓的“锁定对象”。 You may rewrite the code in the following way: 您可以通过以下方式重写代码:


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;
    }
  }
}

Or you may want to create your own lock object and use it: 或者您可能想要创建自己的锁定对象并使用它:


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;
    }
  }
}

Now any number of threads may call the methods of this object randomly, but only one thread at one time will be able to pass the lock and do the actual modification. 现在,任意数量的线程都可以随机调用此对象的方法,但是一次只能有一个线程能够传递锁并进行实际的修改。

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

Or you could do it something like this. 或者,您可以这样做。 The manager class is aware of the position of both threads, and the moveTo method checks that they don't coincide at the same location. 管理器类知道两个线程的位置,并且moveTo方法检查它们在同一位置是否不一致。

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

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

Have the class that manages the maze force the threads to synchronize through itself, and make requests to change their position. 让管理迷宫的类强制线程通过自身进行同步,并发出更改其位置的请求。 The maze manager can then allow or deny requests to move based on the position of other threads. 然后,迷宫管理器可以基于其他线程的位置允许或拒绝移动请求。

Like Sanjay says, prevention is better than cure. 像Sanjay说的那样,预防胜于治疗。 You can partition the cells traversed by the two robots such that they never share the same cell. 您可以对两个机器人遍历的单元进行分区,使它们永远不会共享同一个单元。 If that is not possible, the cure is to use locks for each of the cells. 如果不可能,则解决方法是对每个单元使用锁。 Robots obtain the corresponding lock before moving into the cell and release the lock when done. 机器人在进入单元之前会获得相应的锁,并在完成后释放锁。 This will cause a robot to wait if it is trying to enter the same cell as another robot. 如果机器人试图进入与另一个机器人相同的单元格,这将导致机器人等待。 This is a more decentralized approach than having the maze manager control the moves and will result in less contention. 与让迷宫管理者控制移动相比,这是一种更加分散的方法,将减少争用。

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

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