【问题标题】:Writing a program with 2 threads which prints alternatively编写具有 2 个线程的程序,交替打印
【发布时间】:2012-02-22 03:49:33
【问题描述】:

我最近在一次采访中被问到这个问题。

编写一个包含两个线程(A 和 B)的程序,其中 A 打印 1 , B 打印 2 ,依此类推,直到达到 50。

我们该怎么做呢?

【问题讨论】:

  • 你知道如何编写一个有两个线程的程序吗?如果没有,请参阅您最喜欢的线程教程。如果是这样,那就试着写一个这样的程序,看看会发生什么。
  • 这是家庭作业/作业吗?
  • 顺便说一句,如果我在面试中问这个问题,我希望申请人会提到这是一个非常愚蠢的事情,试图用两个线程来做。作为了解线程 API 的测试,这还不错,但您基本上要求两个线程以单线程方式运行。
  • 在下面提供了一个没有锁、没有同步但使用 Java 8 原子整数和原子布尔值的解决方案。提前致谢。快乐的多线程。 stackoverflow.com/a/70694332/8148637

标签: java multithreading concurrency


【解决方案1】:

赋值的本质是演示一个线程如何向另一个线程发送信号。最常见的方式是使用阻塞队列,但是这里的信号不携带任何信息,所以一个信号量就足够了。

创建使用 2 个信号量参数化的线程类:输入和输出:

class ThreadPrinter implements Runnable {
    int counter;
    Semaphore ins, outs;

    ThreadPrinter(int counter, Semaphore ins, Semaphore outs) {
        this.counter = counter;
        this.ins = ins;
        this.outs = outs;
    }

    @Override
    public void run() {
        for (int i = 0; i < 25; i++) {
            ins.aquire(); // wait for permission to run
            System.out.println("" + counter);
            outs.release();  // allow another thread to run
            counter += 2;
        }
    }

创建 2 个Semaphores 并将它们传递给 2 个线程:

Semaphore a = new Semaphore(1);  // first thread is allowed to run immediately
Semaphore b = new Semaphore(0); // second thread has to wait
ThreadPrinter tp1 = new ThreadPrinter(1, a, b);
ThreadPrinter tp2 = new ThreadPrinter(2, b, a); 

注意信号量ab 以不同的顺序传递。

【讨论】:

  • 这是完美的工作。但是我很难理解它是如何工作的。您能否解释一下由 2 个线程执行的 run() 方法。提前致谢。
  • @PradeepSingh 阅读任何描述信号量的教科书。更喜欢那些将信号量描绘成令牌容器的人。
【解决方案2】:
public class Test {

private static int count = 0;

public static void main(String[] args) throws InterruptedException {

    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {

            for (int i = 0; i < 25; i++) {
                synchronized (CommonUtil.mLock) {
                    incrementCount();
                    CommonUtil.mLock.notify();
                    try {
                        CommonUtil.mLock.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    });
    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {

            for (int i = 0; i < 25; i++) {
                synchronized (CommonUtil.mLock) {
                    incrementCount();
                    CommonUtil.mLock.notify();
                    try {
                        CommonUtil.mLock.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    });
    t1.start();
    Thread.sleep(400);
    t2.start();
    t1.join();
    t2.join();
}

private static void incrementCount() {

    count++;
    System.out.println("Count: " + count + " icnremented by: " +        Thread.currentThread().getName());
}
}
  class CommonUtil {

 static final Object mLock = new Object();
   }

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,预计只使用基础知识,所以我选择等待通知线程之间的共享对象

    public class Message implements Runnable {
    
        private static final int N = 10;
        private Thread thread;
        private static Object object = new Object();
    
        public Message(String name){
            thread = new Thread(this, name);
            thread.start();
        }
    
        public void run(){
            for(int i=0; i<N; i++){
                synchronized (object) {
                    System.out.println(i + "--" + thread.getName());
                    object.notify();
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
            }
        }
    }
    

    在主方法中:

    Message message1 = new Message("Ping");
    Message message2 = new Message("Pong");
    

    【讨论】:

      【解决方案4】:
      public class ThreadCounter implements Runnable {
          private static int count = 0;
      
          private Thread t;
      
          public ThreadCounter(String tName){
              t= new Thread(this, tName);
              t.start();
          }
      
          @Override
          public void run() {
              for(int i=1; i<=5; i++){
                  synchronized (CommonUtil.mLock) {
                      incrementCount(t.getName());
                      CommonUtil.mLock.notify();
                      try {
                          CommonUtil.mLock.wait();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      
          private void incrementCount(String tName){
              System.out.println(tName+": "+(++ThreadCounter.count));
          }
      
          public static void main(String[] args) throws InterruptedException {
              new ThreadCounter("Thread1");
              Thread.sleep(500);
              new ThreadCounter("Thread2");
          }
      
      }
      
      class CommonUtil{
          public static Object mLock = new Object();
      }
      

      【讨论】:

        【解决方案5】:

        嗨,请在这里找到答案...模式 ABABABAB

        package com.abhi.ThreadPractice;
        
            public class Test {
        
                public static void main(String[] args) throws InterruptedException {
        
                  final Object lock = new Object();
                  Thread t1 = new Thread(new Runnable() {
        
                    @Override
                   public void run() {
                    for (int i = 0; i < 10; i++) {
        
                      synchronized (lock) {
                     // count++;
                      System.out.println("A");
                      try {
                       lock.wait();
                       lock.notify();
                      } catch (InterruptedException e) {
                       e.printStackTrace();
                      }
                     }
                    }
                   }
                  });             
        
                   Thread t2 = new Thread(new Runnable() {
        
                    @Override
                   public void run() {
                    for (int i = 0; i < 10; i++) {
                     synchronized (lock) {
                      lock.notify();
                      //count++;
                      System.out.println("B");
                      try {
                       lock.wait();
                      } catch (InterruptedException e) {
                       e.printStackTrace();
                      }
                     }
                    }
                   }
                  });
        
                   t1.start();
                  t2.start();
                  t1.join();
                  t2.join();
        
                  }
        
                }
        

        【讨论】:

          【解决方案6】:

          这是另一种解决方案:

               Thread t1 = new Thread(new Runnable() {
          
                  @Override
                  public void run() {
                      synchronized (lock) {
                          for (int i = 1; i <= 50; i += 2) {
                              System.out.println("T1=" + i);
          
                              t1turn = false;
                                  try {
                                      lock.notifyAll();
                                      lock.wait();
                                  } catch (InterruptedException e) {
                                  }
                          }
                      }
          
                  }
              });
              Thread t2 = new Thread(new Runnable() {
          
                  @Override
                  public void run() {
                      synchronized (lock) {
                          for (int i = 2; i <= 50; i += 2) {
                              if (t1turn)
                                  try {
                                      lock.wait();
                                  } catch (InterruptedException e) {
                                  }
                              System.out.println("T2=" + i);
                              t1turn = true;
                              lock.notify();
                          }
                      }
                  }
              });
              t1.start();
              t2.start();
          

          【讨论】:

            【解决方案7】:

            可能这仍然相关:

            public class MyRunnable implements Runnable {
                public static int counter = 0;
                public static int turn = 0;
                public static Object lock = new Object();
            
                @Override
                public void run() {
                    while (counter < 50) {
                        synchronized (lock) {
                            if (turn == 0) {
            
                                System.out.println(counter + " from thread "
                                        + Thread.currentThread().getName());
                                turn = 1;
                                try {
                                    lock.wait();
                                } catch (InterruptedException e) {
                                    Thread.currentThread().interrupt();
                                }
                            } else {
                                turn = 0;
                                lock.notify();
                            }
            
                        }
                    }
                }
            }
            

            然后是main函数

            public static void main(String[] args) {
                    Thread threadA = new Thread(new MyRunnable());
                    Thread threadB = new Thread(new MyRunnable ());
                    threadA.start();
                    threadB.start();
            }
            

            【讨论】:

              【解决方案8】:
              public class PingPong extends Thread {
              static StringBuilder object = new StringBuilder("");
              
              public static void main(String[] args) throws InterruptedException {
              
                  Thread t1 = new PingPong();
                  Thread t2 = new PingPong();
              
                  t1.setName("\nping");
                  t2.setName(" pong");
              
                  t1.start();
                  t2.start();
              }
              
              @Override
              public void run() {
                  working();
              }
              
              void working() {
                  while (true) {
                      synchronized (object) {
                          try {
                              System.out.print(Thread.currentThread().getName());
                              object.notify();
                              object.wait();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  }
              }
              

              }

              【讨论】:

                【解决方案9】:

                这是我能想到的最简单的解决方案。它使用同步方法并使用 notify() 和 wait() 交替打印数字。希望能帮助到你。 :)

                 public class program implements Runnable
                    {
                        static int count =1;
                        private static final int MAX_COUNT = 50;
                        public synchronized void print ()
                        {
                            System.out.println(Thread.currentThread().getName() + " is printing " + count);
                            count++;
                            notify();
                            try{
                                if(count>MAX_COUNT)
                                    return;
                                wait();
                            }catch (InterruptedException e){ 
                                e.printStackTrace();
                            }
                        }
                        public void run()
                        {
                            for(int i=0;i<MAX_COUNT/2;i++)
                            {
                                print();
                
                            }
                        }
                
                        public static void main(String[] args) {
                
                            program x= new program();
                            Thread t0= new Thread(x);
                            Thread t1=  new Thread(x);
                            t0.start();
                            try
                            {
                                Thread.sleep(1);
                            } catch (InterruptedException e){
                                e.printStackTrace();
                            }
                            t1.start();     
                        }
                
                
                    }
                

                【讨论】:

                  【解决方案10】:
                  //simply use wait and notify and and set a counter and it will do  
                  
                  public class ThreadalternatePrint implements Runnable {
                      static int counter =0; 
                      @Override
                      public synchronized void run() {
                          try {
                              Thread.sleep(10);
                          } catch (InterruptedException e1) {
                              // TODO Auto-generated catch block
                              e1.printStackTrace();
                          }
                  
                          while(counter<51)
                          {   ++counter;
                          notify();
                          System.out.println(Thread.currentThread().getName());
                              try {
                                      wait();
                                  } catch (InterruptedException e) {
                                      // TODO Auto-generated catch block
                                      e.printStackTrace();
                                  }
                          }       
                      }
                  
                      public static void main(String[] args) {
                          ThreadalternatePrint obj1 = new ThreadalternatePrint();
                          Thread Th1 = new Thread(obj1);
                          Thread Th2 = new Thread(obj1);
                          Th1.setName("Thread1");
                          Th2.setName("Thread2");
                          Th1.start();
                          Th2.start();
                      }
                  
                  
                  }
                  

                  【讨论】:

                  • 您的 anwser 实际上不正确(打印线程名称而不是 1,2,3,...),您可能想稍微解释一下您的代码,而不是仅仅转储所有代码。
                  • @glee8e 感谢您的反馈,我将在下面解释代码。好吧,这只是线程方法的简单实现,您可以简单地将名称重命名为 Thread 为 1 或 2 并使用 wait() 并通知您可以通知()另一个线程并交替打印您可以做的另一件事是创建一个 if 条件运行条件中的线程名称。
                  【解决方案11】:
                  public class Testing implements Runnable {
                  private static int counter = 1;
                  private static final Object lock = new Object();
                  
                  public static void main(String[] args)  {
                  
                      Thread t1 = new Thread(new Testing(), "1");
                      t1.start();
                      Thread t2 = new Thread(new Testing(), "2");
                      t2.start();
                  
                  }
                  
                  @Override
                  public void run() {
                      while (counter<=100) {
                          synchronized (lock) {
                              if (counter % 2 == 0) {
                                  System.out.println(counter +" Written By Thread-"+ Thread.currentThread().getName());
                                  counter++;
                                  try {
                                      lock.notifyAll();
                                      lock.wait();
                                  } catch (InterruptedException e) {
                                      e.printStackTrace();
                                  }
                  
                              } else if (counter % 2 == 1) {
                                  System.out.println(counter +" Written By Thread-"+ Thread.currentThread().getName());
                                  counter++;
                  
                                  try {
                                      lock.notifyAll();
                                      lock.wait();
                                  } catch (InterruptedException e) {
                                      e.printStackTrace();
                                  }
                  
                              }
                          }
                      }
                    }
                  }
                  

                  【讨论】:

                  • 这里有很多代码。你应该考虑给它一个解释。
                  【解决方案12】:

                  我使用可重入锁为它创建了一个非常基本的解决方案。

                  package com.multithreding.trylock;
                  
                  import java.util.concurrent.locks.ReentrantLock;
                  
                  public class TryLock extends Thread {
                  
                      static int intitialCount = 50;          //Value till which you want to print
                      int valueToSubtract = 0;                //Value by which difference you want to print the series like 1,2,3
                      static ReentrantLock alternate = new ReentrantLock();
                  
                      public TryLock(String name) {
                          this.setName(name);
                      }
                  
                      public void run() {
                          while (intitialCount > 1) {         
                  
                              if (valueToSubtract > 0) {
                                  alternate.lock();
                                  intitialCount = intitialCount - valueToSubtract;
                                  valueToSubtract = 0;
                                  try {
                                      Thread.sleep(200);
                                  } catch (InterruptedException e) {
                                      // TODO Auto-generated catch block
                                      e.printStackTrace();
                                  }
                                  System.out.println("value Subtracted " + intitialCount + " by the Thread" + this.getName());
                                  alternate.unlock();
                              } else {
                                  try {
                                      Thread.sleep(100);
                                  } catch (InterruptedException e) {
                                      // TODO Auto-generated catch block
                                      e.printStackTrace();
                                  }
                                  valueToSubtract++;
                              }
                          }
                  
                      }
                  
                  }
                  
                  package com.multithreding.trylock;
                  
                  public class AlternatePrint {
                  
                      public static void main(String[] args) throws InterruptedException{
                          //You  can add as many thread to print then in different number of series
                          TryLock t1 = new TryLock("Odd One");
                          TryLock t2 = new TryLock("Even Value");
                          t1.start();
                          t2.start();
                  
                      }
                  
                  }
                  

                  这个解决方案也是模块化的,

                  • 您可以添加“n”个线程来打印备用系列。即一次使用 3 个线程

                  • 您还可以打印差异大于 1 的系列。即 1、3、5 等

                  【讨论】:

                    【解决方案13】:
                    package thread;
                    
                    public class Pingpong extends Thread {
                        static StringBuilder object = new StringBuilder("");
                        static int i=1;
                    
                        @Override
                        public void run() {
                            working();
                        }
                        void working() {
                            while (i<=10) {
                                synchronized (object) {
                                    try {
                                        System.out.println(Thread.currentThread().getName() +"  "+ i);
                                        i++;
                                        object.notify();
                                        object.wait();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                        public static void main(String[] args) throws InterruptedException {
                            Thread t1 = new Pingpong();
                            Thread t2 = new Pingpong();
                            t1.setName("Thread1");
                            t2.setName("Thread2");
                            t1.start();
                            t2.start();
                        }
                    }
                    
                    Thread1  1
                    Thread2  2
                    Thread1  3
                    Thread2  4
                    Thread1  5
                    Thread2  6
                    Thread1  7
                    Thread2  8
                    Thread1  9
                    Thread2  10
                    

                    【讨论】:

                      【解决方案14】:

                      这个答案是通用的,即不仅要从 2 个线程交替打印数字,而且要交替执行 2 个线程。 上述方法值得称道,但这种方法不需要任何锁,而是使用 AtomicInteger 变量和 2 个 AtomicBooleans 来指示一个线程何时完成执行,以便另一个线程可以完成剩余的执行。

                      这将适用于所有 3 种情况:

                      1. 当两个线程的执行次数相同时。
                      2. 当第一个线程在第二个线程之前完成并且第二个线程的执行次数比第一个线程多时。
                      3. 当第二个线程在第一个线程之前完成并且第一个线程的执行次数比第二个线程多时。
                      public class TestAlternateExecutionOfTwoThreads
                      {
                          private static final AtomicInteger count = new AtomicInteger(0);
                          private static final AtomicBoolean firstIsDone = new AtomicBoolean(false);
                          private static final AtomicBoolean secondIsDone = new AtomicBoolean(false);
                      
                          // change the below values to change the number of iterations each thread should 
                          // run. In this example, the initial value are hard-coded but you can change 
                          // them as well.
                          private static final int finalOfFirstThread = 10;
                          private static final int finalOfSecondThread = 109;
                      
                          public static void main(String[] args)
                          {
                              Runnable r1 = () -> {
                                  int i = 1;
                                  for(; i <= finalOfFirstThread; )
                                  {
                                      while(count.get() == 0)
                                      {
                                          System.out.println(i);
                                          count.incrementAndGet();
                                          i++;
                                      }
                                      if(count.get() == 1 && secondIsDone.get() && i != (finalOfFirstThread + 1))
                                      {
                                          System.out.println(i);
                                          i++;
                                      }
                                  }
                                  firstIsDone.set(true);
                              };
                      
                              Runnable r2 = () -> {
                                  int j = 100;
                                  for (; j <= finalOfSecondThread; )
                                  {
                                      while(count.get() == 1)
                                      {
                                          System.out.println(j);
                                          count.decrementAndGet();
                                          j++;
                                      }
                                      if(count.get() == 0 && firstIsDone.get() && j != (finalOfSecondThread + 1))
                                      {
                                          System.out.println(j);
                                          j++;
                                      }
                                  }
                                  secondIsDone.set(true);
                              };
                      
                              Thread t1 = new Thread(r1);
                              Thread t2 = new Thread(r2);
                      
                              t1.start();
                              t2.start();
                      
                          }
                      }
                      

                      【讨论】:

                        【解决方案15】:

                        我想这可能会有所帮助。 虽然它不是标准的,但我希望它提供一种更简单的方法。

                        public class ThreadDemo
                        {
                            public static void main (String [] args)
                            {
                                PrintDemo pd=new PrintDemo();     
                                MyThread1 mt1 = new MyThread1 ("T1",pd);
                                MyThread2 mt2 = new MyThread2 ("T2",pd);     
                                mt1.start ();
                                mt2.start();
                            }
                        }
                        class PrintDemo {
                            private boolean oddFlag=true;
                            public synchronized void printOdd(int i,String tName){
                                if(oddFlag==false){
                                    try {
                                        wait();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }   
                                }else{
                                    System.out.println("\nThread "+tName+" count:"+i);
                                    oddFlag=false;
                                    notify();
                                }
                            }
                            public synchronized void printEven(int i,String tName){
                                if(oddFlag==true){
                                    try {
                                        wait();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }   
                                }else{
                                    System.out.println("\nThread "+tName+" count:"+i);
                                    oddFlag=true;
                                    notify();
                                }
                            }   
                        }
                        class MyThread1 extends Thread
                        {
                            private PrintDemo pd;
                            private String name;
                        
                            MyThread1(String threadName,PrintDemo pd){
                                this.name=threadName;
                                this.pd=pd;
                            }  
                            public void run ()  
                            {
                               for(int i=1;i<=50;i+=2){
                                    pd.printOdd(i,name);
                               }
                            }
                        }
                        class MyThread2 extends Thread
                        {
                            private PrintDemo pd;
                            private String name;    
                            MyThread2(String threadName,PrintDemo pd){
                                this.name=threadName;
                                this.pd=pd;
                            }   
                            public void run ()
                            {
                                for(int i=2;i<=50;i+=2){
                                    pd.printEven(i,name);                   
                                }
                            }
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 2017-10-21
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多