How to make sure two threads printing even odd numbers maintain even first then odd order for this implementation?

后端 未结 3 1566
独厮守ぢ
独厮守ぢ 2021-01-16 01:24

I have created two runnable jobs: PrintEvenNumbersJob and PrintOddNumbersJob and spawned two threads to execute these jobs. This seems to work perfectly fine! But I smell so

相关标签:
3条回答
  • 2021-01-16 01:34

    Have you try using Semaphores? It's easier because you don't need to worry about the order that wait and notify are called (if you call notify before the wait, it's "lost")

    Sample code:

    import java.util.concurrent.*;
    
    public class Test {
    
        private final Semaphore oddJobPermits = new Semaphore(0);
        private final Semaphore evenJobPermits = new Semaphore(1);
    
        private class EvenJob implements Runnable {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        evenJobPermits.acquire();
                        System.out.println(i * 2);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } finally {
                        oddJobPermits.release();
                    }
                }
            }
        }
    
        private class OddJob implements Runnable {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        oddJobPermits.acquire();
                        System.out.println(i * 2 + 1);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } finally {
                        evenJobPermits.release();
                    }
                }
            }
        }
    
        public void run() {
            new Thread(new EvenJob()).start();
            new Thread(new OddJob()).start();
        }
    
        public static void main(String[] args) {
            new Test().run();
        }
    
    }
    
    0 讨论(0)
  • 2021-01-16 01:47

    I believe you will need a referee:

    public class Referee {
        private boolean evensTurn = true;
    
        public void waitMyTurn(boolean even) {
            synchronized(this) {
                while (even != evensTurn) {
                    try {
                        wait();
                    } finally {
                    }
                }
            }
        }
    
        public void done() {
            synchronized(this) {
                evensTurn = !evensTurn;
                notify();
            }
        }
    }
    
    public class PrintEvenNumbersJob implements Runnable {
    
        private Referee referee;
    
        public PrintEvenNumbersJob(Referee referee) {
            this.referee = referee;
        }
    
        @Override
        public void run() {
            for (int i = 0; i <= 10; i += 2) {
    
                referee.waitMyTurn(true);
    
                System.out.println(i);
    
                referee.done();
            }
        }
    }
    
    public class PrintOddNumbersJob implements Runnable {
    
        private Referee referee;
    
        public PrintOddNumbersJob(Referee referee) {
            this.referee = referee;
        }
    
        @Override
        public void run() {
            for (int i = 0; i <= 10; i += 2) {
    
                referee.waitMyTurn(false);
    
                System.out.println(i);
    
                referee.done();
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-16 01:53

    I tried and tested this code. It works using Semaphore

    public class TestSemaphore
    {
    
        public static void main(String[] args)
            throws Exception
        {
            AtomicInteger count = new AtomicInteger();
            Semaphore s = new Semaphore(1, true);
            Semaphore t = new Semaphore(1, true);
    
            OddNumberThread oThread = new OddNumberThread(count, s, t);
            EvenNumberThread eThread = new EvenNumberThread(count, s, t);
    
            eThread.start();
            oThread.start();
        }
    
        static class EvenNumberThread
            extends Thread
        {
            private AtomicInteger count;
    
            private Semaphore s, t;
    
            public EvenNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
            {
                super("Even");
                count = pCount;
                s = pS;
                t = pT;
            }
    
            @Override
            public void run()
            {
                // Make this thread wait until even thread starts, Order will be incorrect if removed these lines.
                s.acquireUninterruptibly();
                while (count.intValue() <= 10)
                {
                    try
                    {
                        // Double checking to make it work
                        s.acquireUninterruptibly();
    
                        System.out.println(getName() + " " + count.getAndIncrement());
                    }
                    finally
                    {
                        t.release();
                    }
                }
            }
        }
    
        static class OddNumberThread
            extends Thread
        {
            private AtomicInteger count;
    
            private Semaphore s, t;
    
            public OddNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
            {
                super("Odd");
                count = pCount;
                s = pS;
                t = pT;
            }
    
            @Override
            public void run()
            {
                // Start this thread first and start printing, Order will be incorrect if removed these lines.
                t.acquireUninterruptibly();
                s.release();
    
                while (count.intValue() <= 10)
                {
                    try
                    {
                        t.acquireUninterruptibly();
    
                        System.out.println(getName() + " " + count.getAndIncrement());
                    }
                    finally
                    {
                        s.release();
                    }
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题