2016-04-26 100 views
0

所以,嘿大家好,我實際上是編碼方面的新人,甚至在基本問題上也遇到很多問題。Java多線程:飛機和跑道案例研究示例

所以我的講師給這個案例研究:模擬一次可以容納1架飛機着陸的飛機數量和4條跑道。如果所有4條跑道都被佔用,其他飛機必須等待其中一架或更多飛機起飛。對我來說很難,所以我先嚐試2跑道和4架飛機。

平面是線程類,跑道是普通類。我到目前爲止已經完成:

  1. 主類

    public class Main { 
         public static void main(String[] args) { 
          Runway r[] = new Runway[2]; 
          for (int i = 0; i < r.length; i++) { 
           r[i] = new Runway(i); 
          } 
    
          Plane p[] = new Plane[4]; 
    
          for (int i = 0; i < p.length; i++){ 
           p[i] = new Plane(i, r[0], r[1]); 
           p[i].start(); 
          } 
         } 
        } 
    
  2. 跑道類

    public class Runway { 
         private int id; 
         private Lock l; 
         public boolean available = true; 
    
         public Runway(int id){ 
          this.id = id; 
          l = new ReentrantLock(); 
         } 
    
         public boolean landing(int idp){ 
          boolean i; 
          i = l.tryLock(); 
          if (i == true) { 
           available = false; 
           System.out.println("Plane " + idp + " is landing on Runway: " + id); 
          } 
          return i; 
         } 
    
         public void takeOff(int idp){ 
          System.out.println("Plane " + idp + " is take off from Runway: " + id); 
          available = true; 
          l.unlock(); 
         } 
        } 
    
  3. 平面類

    public class Plane extends Thread { 
         private Runway r1, r2; 
         private int id, tag; 
         private boolean i = false; 
    
         public Plane(int id, Runway r1, Runway r2){ 
          this.id = id; 
          this.r1 = r1; 
          this.r2 = r2; 
         } 
    
         public void run(){ 
          if (i == false) { 
           if (r1.available == true) { 
            i = r1.landing(id); 
            tag = 1; 
           } else if (r2.available == true) { 
            i = r2.landing(id); 
            tag = 2; 
           } 
          } 
    
          sleep(); 
    
          if (tag == 1 & i == true){ 
           r1.takeOff(id); 
           i = false; 
          } else if (tag == 2 & i == true) { 
           r2.takeOff(id); 
           i = false; 
          } 
         } 
    
         private void sleep(){ 
          try { 
           Thread.sleep(new Random().nextInt(8)*100); 
          }catch (Exception e){} 
         } 
        } 
    

這是結果...

Plane 1 is landing on Runway: 0 
Plane 3 is landing on Runway: 1 
Plane 1 is take off from Runway: 0 
Plane 3 is take off from Runway: 1 

Process finished with exit code 0 

並非所有飛機的落下,我知道這是基本的,但任何幫助表示讚賞:d

+0

是否允許使用「同步」語句? – gapvision

+0

是的,我可以使用任何方法bro @gapvision –

+1

你的代碼只包含一次嘗試,所以它只會做一次嘗試,如果嘗試失敗,什麼也不做。所以最小的做法是添加一個*循環*直到嘗試成功。 – Holger

回答

0

這裏有一個方法是,以同步訪問共享的可替代狀態。將變量標記爲易失性是對運行時開銷較小的同步的「精簡」替代方案。它告訴JVM的內存管理器,以保證該變量的「活躍度」的所有訪問線程

編輯

  • 後,我意識到,volatile關鍵字並不能保證手術區周圍的原子我做了一些修改試圖降落飛機。
  • 我也意識到IDS從不施工後修改,所以不需要volatile關鍵字

進口的java.util。*; import java.util.concurrent.atomic.AtomicReference;

public class Airport { 

    /** 
    * if number of planes is less than or equal to twice the number of runways 
    * the execution will terminate ie all planes that want to land 
    * will land and all those that wish to take off will take off . 
    * Otherwise there wont be enough runways for the landing planes and the execution will 
    * go on indefinitely . 
    */ 
    static Runway r[] = new Runway[10]; 
    static Plane p[] = new Plane[20]; 

    public static void main(String[] args) { 
     //instantiate array of planes 
     for (int i = 0; i < p.length; i++){ 
      p[i] = new Plane(i); 
     } 

     //instantiate runways and allocate planes to runways 
     List<Plane> planes = Arrays.asList(p); 
     Iterator<Plane> iterator; 
     Collections.shuffle(planes); 
     iterator= planes.iterator(); 
     for (int i = 0; i < r.length; i++) { 
      Plane p; 
      try { 
       p= iterator.next(); 
      }catch (RuntimeException e){ 
       p= null; 
      } 
      r[i] = new Runway(i,p); 
     } 

     //display initial state 
     for (int i = 0; i < p.length; i++){ 
      Runway runway=getUsedRunway(p[i]); 
      System.out.println("plane "+p[i].id + " is "+(runway==null?"waiting to land":("on runway "+runway.id))); 
     } 

     System.out.println("======== Begin! ============"); 

     //let the games begin 
     for (int i = 0; i < p.length; i++){ 
      p[i].start(); 
     } 
    } 


    private static class Runway { 
     //only ever read after construction . no need for special handling for concurreny 
     private int id; 

     /** 
     * volatile keyword gives atomic read and atomic write operation in isolation . 
     * However to land the plane we need to set the runway's plane reference value based on its current value . 
     * This scenario is called out specifically by B Goetz in this article https://www.ibm.com/developerworks/java/library/j-jtp06197/ 
     * (and in his book Javas one in which volatile is insufficient for thread safety 
     * We need an atomic compare and set 
     */ 
     private AtomicReference<Plane> planeAtomicReference; 

     public Runway(int i, Plane p) { 
      id =i; 
      planeAtomicReference = new AtomicReference<>(); 
      planeAtomicReference.set(p); 
     } 
    } 


    private static class Plane extends Thread { 
     //only ever read after construction . no need for special handling for concurreny 
     private int id; 

     Plane(int i){ 
      id=i; 
     } 

     @Override 
     public void run() { 
      Runway runway=getUsedRunway(this); 
      if(runway==null){ 
       System.out.println("plane "+id+" wants to land"); 
       Runway availableRunway = getAvailableRunway(); 
       while ((availableRunway=atomicallyAttempToLandPlane(this))==null) { 
        System.out.println("no runway available yet for plane " + id); 
        try { 
         sleep(30); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
       System.out.println("landed plane "+id+" on runway "+availableRunway.id); 
      }else { 
       System.out.println("plane "+id+" wants to take off from runway "+runway.id); 
       runway.planeAtomicReference.set(null); 
       System.out.println("plane "+id+" has taken off from runway "); 
      } 
     } 

     /** 
     * 
     * @param plane 
     * @return 
     */ 
     private Runway atomicallyAttempToLandPlane(Plane plane) { 
      for (int i = 0; i < r.length; i++) { 
       if(r[i].planeAtomicReference.compareAndSet(null,plane)){ 
        return r[i]; 
       } 
      } 
      return null; 
     } 
    } 

    /** 
    * does not require synchronization since the size of the arrays is fixed during execution and the elements 
    * to which they refer is also fixed . only the internal state of elements themselves is open to change 
    * and that has been guaranteed by marking it as volatile as well as additional atomic behaviour 
    * @return 
    */ 
    private static Runway getAvailableRunway(){ 
     for (int i = 0; i < r.length; i++) { 
      if(r[i].planeAtomicReference.get() ==null){ 
       return r[i]; 
      } 
     } 
     return null; 
    } 



    /** 
    * does not require synchronization since the size of the arrays is fixed during execution and the elements 
    * to which they refer is also fixed . only the internal state of elements themselves is open to change 
    * and that has been guaranteed by marking it as volatile as well as additional atomic behaviour 
    * @param plane 
    * @return 
    */ 
    private static Runway getUsedRunway(Plane plane){ 
     for (int i = 0; i < r.length; i++) { 
      final Plane planeOnRunway = r[i].planeAtomicReference.get(); 
      if(planeOnRunway !=null && planeOnRunway.id==plane.id){ 
       return r[i]; 
      } 
     } 
     return null; 
    } 


}