繁体   English   中英

如何确保两个线程打印偶数为偶数,对于此实现,它先保持偶数然后是奇数?

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

我创建了两个可运行的作业:PrintEvenNumbersJob和PrintOddNumbersJob,并生成了两个线程来执行这些作业。 这似乎工作得很好! 但是我对这种实现感到有些怀疑。 我可以对此实施提出一些意见和建议吗?

我看到的这种实现的问题是,仅当线程1首先获得对对象锁的锁定时,程序才会终止,否则它将打印奇数第一个偶数二阶,并且不会终止,除非我在之后提供另一个语句“ lock.notify”用于PrintEvenNumbersJob中的语句(如此实现中所示)。 我的问题是如何确保先执行thread1。

public class PrintEvenNumbersJob implements Runnable {

private Object lock;

public PrintEvenNumbersJob(Object lock) {
    this.lock = lock;
}

@Override
public void run() {
    synchronized (lock) {
        for (int i = 0; i <= 10; i += 2) {

            lock.notify();

            System.out.println(i);

            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        lock.notify(); // not required if thread1 gains lock first
    }
}

}


public class PrintOddNumbersJob implements Runnable {

private Object lock;

public PrintOddNumbersJob(Object lock) {
    this.lock = lock;
}

@Override
public void run() {
    synchronized (lock) {
        for (int i = 1; i < 10; i += 2) {

            lock.notify();

            System.out.println(i);

            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        lock.notify();
    }
}

}



public class EvenOddManager {

public static void main(String[] args) {

    Object lock = new Object();

    PrintEvenNumbersJob printEvenNumbersJob = new PrintEvenNumbersJob(lock);
    PrintOddNumbersJob printOddNumbersJob = new PrintOddNumbersJob(lock);

    Thread thread1 = new Thread(printEvenNumbersJob);
    Thread thread2 = new Thread(printOddNumbersJob);

    thread2.start();
    thread1.start();

}

}

您是否尝试过使用信号量? 这样比较容易,因为您不必担心等待和通知的调用顺序(如果在等待之前调用通知,则“丢失”)

样例代码:

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();
    }

}

我相信您将需要一名裁判:

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();
        }
    }
}

我尝试并测试了此代码。 它可以使用信号量

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();
                }
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM