2012-10-24 57 views
3

該程序將生成n-LIZARD線程和1個CAT線程。 「喚醒」LIZARD線程必須執行「吃飯」任務。蜥蜴必須從西米棕櫚到猴草才能「吃」然後跨過。貓線會在特定時間後醒來,然後檢查以確保一次不超過4個LIZARD線。這個想法是讓這個「世界」或程序運行,直到120秒的特定時間過去並讓蜥蜴免受貓侵害。一般用於Java中的信號量

我對信號量班知之甚少,想知道如何實現和放置一個多重排斥和一個常規的信號量。使用.acquire()和.release()來控制此程序中的線程。

我知道,互斥將獲得一個線程只(所以我想這是可以用來控制貓線程(讓我知道如果我錯了)

所以我經常信號燈必須保護的「衛道士」 。

我有這個想法下來,我只是需要一些幫助的位置。我評論的一切,所以你都可以在什麼我嘗試(失敗)明確做:)

import java.util.ArrayList; 
import java.util.concurrent.Semaphore; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

/** 
*/ 
public class LizardsSync 
{ 
    /* 
    * Set this to the number of seconds you want the lizard world to 
    * be simulated. 
    * Try 30 for development and 120 for more thorough testing. 
    */ 
    private static int WORLDEND = 120; 

    /* 
    * Number of lizard threads to create 
    */ 
    private static int NUM_LIZARDS =20; 

    /* 
    * Maximum lizards crossing at once before alerting cats 
    */ 
    private static int MAX_LIZARD_CROSSING = 4; 

    /* 
    * Maximum seconds for a lizard to sleep 
    */ 
    private static int MAX_LIZARD_SLEEP_TIME = 3; 

    /* 
    * Maximum seconds for a lizard to eat 
    */ 
    private static int MAX_LIZARD_EAT_TIME = 5; 

    /* 
    * Number of seconds it takes to cross the driveway 
    */ 
    private static int CROSS_TIME = 2; 

    /* 
    * Number of seconds for the cat to sleep. 
    */ 
    private static int MAX_CAT_SLEEP; 

    /* 
    * A counter that counts the number of lizzards crossing sago to monkey grass 
    */ 
    int numCrossingSago2MonkeyGrass = 0; 

    /* 
    * A counter that counts the number of lizzards crossing monkey grass to sago 
    */ 
    int numCrossingMonkeyGrass2Sago = 0; 

    /** 
    * A semaphore to protect the crossway. 

    */ 
    Semaphore semaphoreCrossway = new Semaphore(MAX_LIZARD_CROSSING); 

    /** 
    * A semaphore for mutual exclusion. 
    */ 
    Semaphore mutex = new Semaphore(1); 

    // on both semaphores, you can call acquire() or release() 
    /* 
    * Indicates if the world is still running. 
    */ 
    private static boolean running = true; 

    /* 
    * Indicates if you want to see debug information or not. 
    */ 
    private static boolean debug = true; 


    public void go() 
    { 
     ArrayList<Thread> allThreads = new ArrayList<Thread>(); 

     // create all the lizzard threads 
     for (int i=0; i < NUM_LIZARDS; i++) 
     {  allThreads.add(new LizardThread(i)); 
      allThreads.get(i).start(); 
} 
     // create the cat thread 
     Thread CatThread = new CatThread(); 
     CatThread.start(); 

     // let the world run for a while 
     sleep (WORLDEND); 

     // terminate all threads 
     running = false; 
     // wait until all threads terminate by joining all of them 
     for (int i=0; i < NUM_LIZARDS; i++) { 
      try { 
       allThreads.get(i).join(); 
      } catch (InterruptedException ex) { 
       System.err.println ("unable to join thread, " + ex.getMessage()); 
      } 
     } 
    } 
     /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     // starts the program 
     new LizardsSync().go(); 
    } 

    /** 
    * Models a cat thread. 
    */ 
    public class CatThread extends Thread { 


     /** 
     * @see java.lang.Runnable. 
     */ 
     @Override 
     public void run() 
     { 
      while (running) { 


        // sleep for a while 
        catSleep(); 
        // check on lizzards 

        checkCrossway(); 

      } 
     } 

     /** 
     * Puts cat thread to sleep for a random time. 
     */ 
     public void catSleep() 
     { 
      int sleepSeconds = 1 + (int)(Math.random()*MAX_CAT_SLEEP); 

      if (debug) { 
       System.out.println ("Cat is sleeping for " + sleepSeconds + " seconds."); 
       System.out.flush(); 
      } 
      try { 
       sleep(sleepSeconds*1000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(LizardsSync.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      if (debug) { 
       System.out.println ("Cat awakes."); 
       System.out.flush(); 
      } 
     } 

     /** 
     * Simulates cat checking the crossway. 
     */ 
     public void checkCrossway() 
     { 

      if (numCrossingMonkeyGrass2Sago + numCrossingSago2MonkeyGrass > MAX_LIZARD_CROSSING) { 
       System.out.println ("The cat says yum!"); 
       System.out.flush(); 
        System.exit(-1); 
      } 
     } 
    } 

    /** 
    * Models a lizard thread. 
    */ 
    public class LizardThread extends Thread { 

     private int _id; 

     /** 
     * Creates a new lizard thread. 
     * 
     * @param id the id assigned to the lizard thread 
     */ 
     public LizardThread(int id) 
     { 
      _id = id; 
     } 

     /** 
     * @see java.lang.Runnable. 
     */ 
     @Override 
     public void run() 
     {  

      while (running) { 
       // sleep for a while in sago 
       lizardSleep(); 
       // wait until safe to cross from sago to monkey grass 
       sagoToMonkeyIsSafe(); 
       // cross path to monkey grass 
       crossedOverToMonkey(); 
       // eat in the monkey grass 
       lizardEat(); 
       // wait untill its safe to cross back to sago 
       monkeyToSagoIsSafe(); 
       // cross from cross monkey grass to sage 
       crossMonkeyToSago(); 
      } 
     } 

     /** 
     * This tests if it is safe to travel from sago to monkey. 
     * 
     */ 
     public void sagoToMonkeyIsSafe() 
     { 

       if (debug) { 
        System.out.println ("Lizard [" + _id + "] checks sago -> monkey grass."); 
        System.out.flush(); 
       } 



       if (debug) { 
        System.out.println ("Lizard [" + _id + "] thinks sago -> monkey grass is safe."); 
        System.out.flush(); 
       } 


     } 

     /** 
     * Indicates that lizard crossed over to monkey grass. 
     */ 
     public void crossedOverToMonkey() 
     { 
      if (debug) { 
       System.out.println ("Lizard [" + _id + "] made it to monkey grass."); 
       System.out.flush(); 
      } 

      if (debug) { 
       System.out.println ("Lizard [" + _id + "] thinks monkey grass -> sago is safe."); 
       System.out.flush(); 

      } 
     } 


     /** 
     * This tests if it is safe to travel from monkey to sago. 
     */ 
     public void monkeyToSagoIsSafe() 
     { 

      if (debug) { 
       System.out.println ("Lizard [" + _id + "] checks monkey grass -> sago."); 
       System.out.flush(); 
      } 



      if (debug) { 
       System.out.println ("Lizard [" + _id + "] thinks monkey grass -> sago is safe."); 
       System.out.flush(); 

      } 
     } 

     /** 
     * Indicates that lizard crossed over to sago. 
     */ 
     public void crossedOverToSago() 
     { 
      if (debug) { 
       System.out.println ("Lizard [" + _id + "] made it to sago."); 
       System.out.flush(); 
      } 

      if (debug) { 
       System.out.println ("Lizard [" + _id + "] thinks sago -> monkey grass is safe."); 
       System.out.flush(); 
     } 
     } 
     /** 
     * Indicates that lizard is crossing over from monkey to sago. 
     */ 
     void crossMonkeyToSago() 
     { 
      if (debug) { 
       System.out.println ("Lizard [" + _id + "] is crossing monkey grass to sago."); 
       System.out.flush(); 
      } 

      numCrossingMonkeyGrass2Sago++; 

      // simulate walk 
      try { 
       sleep(CROSS_TIME*1000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(LizardsSync.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      numCrossingMonkeyGrass2Sago--; 
     } 

     /** 
     * Indicates that lizard is crossing over from sago to monkey. 
     */ 
     void crossSagoToMonkey() 
     { 

      if (debug) { 
       System.out.println ("Lizard [" + _id + "] is crossing sago to monkey grass."); 
       System.out.flush(); 
      } 

      numCrossingSago2MonkeyGrass++; 

      // simulate walk 
      try { 
       sleep(CROSS_TIME*1000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(LizardsSync.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      numCrossingSago2MonkeyGrass--; 
     } 


     /** 
     * Puts lizard thread to sleep for a random amount of time. 
     */ 
     public void lizardSleep() 
     { 
      int sleepSeconds = 1 + (int)(Math.random()*MAX_LIZARD_SLEEP_TIME); 

      if (debug) { 
       System.out.println ("Lizard [" + _id + "] is sleeping for " + sleepSeconds + " seconds."); 
       System.out.flush(); 
      } 
      try { 
       sleep(sleepSeconds*1000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(LizardsSync.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      if (debug) { 
       System.out.println ("Lizard [" + _id + "] awakes."); 
       System.out.flush(); 
      } 
     } 

     /** 
     * Simulates lizard eating for a random amount of time. 
     */ 
     public void lizardEat() 
     { 
      int eatSeconds = 1 + (int)(Math.random()*MAX_LIZARD_EAT_TIME); 

      if (debug) { 
       System.out.println ("Lizard [" + _id + "] is eating for " + eatSeconds + " seconds."); 
       System.out.flush(); 
      } 
      try { 
       sleep(eatSeconds*1000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(LizardsSync.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      if (debug) { 
       System.out.println ("Lizard [" + _id + "] finished eating."); 
       System.out.flush(); 
      } 
     } 
    } 


    /** 
    * Puts current thread to sleep for a specified amount of time. 
    * 
    * @param seconds the number of seconds to put the thread to sleep 
    */ 
    private static void sleep(int seconds) 
    { 
     try { 
      Thread.sleep(seconds*1000); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(LizardsSync.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

} 

回答

1

每當你要交叉路徑,您將撥打acquire和只要你有交叉路徑,你可以撥打release

Semaphore semaphore= new Semaphore(No of Lizards that can cross the road at a time); 


sagoToMonkeyIsSafe();<-- semaphore.acquire(); as crossing the path start 
// cross path to monkey grass 
crossedOverToMonkey();<---semaphore.release(); as crossing the path end 

monkeyToSagoIsSafe();<-- semaphore.acquire(); as crossing the path start 
// cross from cross monkey grass to sage 
crossMonkeyToSago();<---semaphore.release(); as crossing the path end 
+0

是的,這是我的想法。我猜我可以使用互斥體作爲貓線程的失敗保險,以保持它只檢查一次。 – wat

+0

@wat如果你想讓一個交叉一次,然後使用信號量與計數器1,如果你想更多的交叉然後增加信號量 –

+1

@wat但是那麼你的貓總是餓了;) –