Java中信号量的一般用法

时间:2012-10-24 04:48:12

标签: java

该程序将生成n-LIZARD线程和1个CAT线程。 在“醒来”时,LIZARD线程必须执行“吃”任务。蜥蜴必须从西米棕榈树到猴子草交叉“吃”,然后交叉回来。 cat线程将在给定时间后唤醒然后检查以确保一次不超过4个LIZARD线程“交叉”。我们的想法是让“世界”或程序运行,直到120秒的给定时间过去,并使蜥蜴免受猫的伤害。

我对信号量类知之甚少,并且想知道如何实现和放置mutuel排除以及常规信号量。使用.acquire()和.release()来控制此程序中的线程。

我知道互斥只会获得一个线程(所以我认为这可以用来控制cat线程(如果我错了就告诉我)

所以我的常规信号量必须保护“十字路口”。

我有这个想法我只需要一些安置帮助。我评论了所有内容,所以你们都可以清楚我正在尝试(失败)做什么:)

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 个答案:

答案 0 :(得分: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