2016-04-26 32 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; 
    } 


}