【问题标题】:Thread Synchronization - How to execute threads alternatively线程同步 - 如何交替执行线程
【发布时间】:2010-02-14 19:58:02
【问题描述】:

我一直在尝试使用 wait() 和 notify() 解决涉及线程通信的问题。基本上我有 2 个线程 T1 和 T2,我希望它们按以下顺序执行

T1、T2、T1、T2 .....我怎样才能做到这一点?

实际问题:有 2 个线程 T1 - 打印奇数(例如 1 - 100)和 T2 - 打印偶数(1 - 100)。现在,输出应该是 1, 2, 3, 4 , 5 , .... 100

【问题讨论】:

  • 单线程运行任务?
  • 如果你想要同步的东西,为什么要使用线程运行?
  • 我产生了两个线程。我希望它们与首先执行的第一个线程交替执行
  • 与仅在一个线程中运行代码相比,这给您带来了哪些优势?
  • 我猜这是一个关于同步的家庭作业问题,而不是一个需要解决的实际问题。

标签: java multithreading synchronization wait


【解决方案1】:

您描述了生产者-消费者模式。

它是许多 Java 书籍中描述的 Java 实现,包括 M.Grand “Java 中的模式。第一卷”和 Naughton 和 Schildt 的“Java 2:完整参考”。

基本思想:两个线程都应该使用 1 个监视器(即它们的代码应该在 synchronized(monitor) {} 块内)。您还需要一些标志变量,它应该指示两个线程中的哪一个当前应该工作。

当你的一个线程在同步块内时,它应该检查标志变量是否轮到他来做这项工作。如果是,让它工作,然后更改标志值,然后通知所有等待线程。如果没有,那么它应该等待。

【讨论】:

  • 不完全是这样。基本上我有2个线程,假设一个打印出a,另一个打印出b。现在我想打印一个序列ababab.....
  • @sai 您可以使用生产者-消费者的解决方案作为解决方案。
【解决方案2】:

查看 java.util.concurrent 包,特别是 Exchanger

【讨论】:

    【解决方案3】:

    您正在尝试并行化多步骤流程,对吗?如果是这样,请参阅我的回答 here 以获取一种方法和一些工作代码来做到这一点。答案涉及一个ExecutorService(或两个)和一个或多个工作队列。

    对于这种方法,您的处理需要能够适应 Runnable,以及用于处理的中间状态信息。 您将每个步骤作为Runnable 提供给ExecutorService,这将添加第二个 Runnable 以执行下一步。 这保持了执行顺序,但可以让您有效地运行尽可能多的线程你希望并行。

    :编辑:

    正如另一个人所建议的,如果您明确希望将处理限制为 2 个线程,则可以使用 Exchanger 库类。我更喜欢上述方法,因为它保持了执行顺序并允许您充分使用现代 4 核(和 8 核)系统。它还应该减少一点同步。

    【讨论】:

      【解决方案4】:

      如果 T1 和 T2 是 Runnable 接口的 2 个不同实现,T1 是一个只打印奇数 (1,3,...) 的线程,而 T2 是一个打印偶数 (1,2...) 的线程..),这可以通过在共享监视器上使用 wait() 和 notify() 方法来完成。重要的是每个线程在打印其值之前检查共享标志。以下代码有效;

      //The shared monitor
      public class Mutex {
      public static boolean oddFlag;
      
      }
      
      //The Thread that is supposed to print Odd numbers (assuming an upper limit of 99)
      public class OddPrinter implements Runnable {
      private Mutex mutex;
      
      public OddPrinter(Mutex mutex) {
          this.mutex = mutex;
      }
      
      public synchronized void run() {
          System.out.println("Started Thread: OddPrinter");
          int i;
          for(i=1; i<100; i+=2 ) {
              synchronized (mutex) {
                  while(!Mutex.oddFlag) {
                      try {
                          mutex.wait();
                      } catch (InterruptedException ie) {
                          Thread.currentThread().interrupted();
                      }
                  }
      
                  if(Mutex.oddFlag == true) {
                      System.out.println("Print from OddPrinter: "+i);
                      Mutex.oddFlag = false;
                      mutex.notify();
                  }
      
      
              }
          }
          System.out.println("Finished Thread: OddPrinter: "+i);
      }
      
      }
      
      //The Thread that is supposed to print Odd numbers (assuming an upper limit of 98)
      public class EvenPrinter implements Runnable {
      private Mutex mutex;
      
      public EvenPrinter(Mutex mutex) {
          this.mutex = mutex;
      }
      
      public synchronized void run() {
          System.out.println("Started Thread: EvenPrinter");
          int i;
          for(i=2; i<100; i+=2) {
              synchronized (mutex) {
                  while(Mutex.oddFlag) {
                      try {
                          mutex.wait();
                      } catch (InterruptedException ie) {
                          Thread.currentThread().interrupted();
                      }
                  }
      
                  if(!(Mutex.oddFlag == true)) {
                      System.out.println("Print from EvenPrinter: "+i);
                      Mutex.oddFlag = true;
                      mutex.notify();
                  }
      
              }
          }
          System.out.println("Finished Thread: EvenPrinter: "+i);
      }
      
      }
      
      //The test harness that executes the threads
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.TimeUnit;
      
      public class NumberPrinterTest {
      
      public static void main(String[] args) throws Exception{
          ExecutorService es = Executors.newFixedThreadPool(2);
      
          Mutex mutex = new Mutex();
          OddPrinter op = new OddPrinter(mutex);
          EvenPrinter ep = new EvenPrinter(mutex);
          Mutex.oddFlag = true;
          es.execute(op);
          es.execute(ep);
      
          if(null != es){
              es.shutdown();
              try {
                  es.awaitTermination(1, TimeUnit.MINUTES);
              } catch (InterruptedException e) {
                  Thread.currentThread().interrupted();
              }
          }
      
      }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-27
        • 1970-01-01
        相关资源
        最近更新 更多