【问题标题】:How to make sure two threads printing even odd numbers maintain even first then odd order for this implementation?对于此实现,如何确保打印偶数奇数的两个线程先保持偶数,然后再保持奇数?
【发布时间】:2014-04-10 00:24:40
【问题描述】:

我创建了两个可运行的作业:PrintEvenNumbersJob 和 PrintOddNumbersJob,并生成了两个线程来执行这些作业。这似乎工作得很好!但是我闻到了这个实现的可疑之处。我可以就这个实现提供一些 cmets 和建议吗?

我在这个实现中看到的问题是,程序只有在 thread1 首先获得对象锁的锁时才会终止,否则它会打印奇数的第一个偶数个第二个顺序,并且除非我提供另一个语句,否则它不会终止PrintEvenNumbersJob 中的 for 语句之后的“lock.notify”(如在此实现中)。我的问题是如何确保首先执行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();

}

}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    您是否尝试过使用信号量?这更容易,因为您无需担心调用 wait 和 notify 的顺序(如果您在等待之前调用 notify,它会“丢失”)

    示例代码:

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

    【讨论】:

      【解决方案2】:

      我相信你需要一个裁判:

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

      【讨论】:

        【解决方案3】:

        我尝试并测试了这段代码。它使用信号量工作

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-08-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-17
          • 1970-01-01
          相关资源
          最近更新 更多