【问题标题】:3 threads to print alternate values in sequence3个线程按顺序打印备用值
【发布时间】:2013-03-10 13:39:07
【问题描述】:

我正在尝试创建一个实现,其中多个线程打印序列的替代值。所以这里 thread1 将打印 1,4,7 thread2 将打印 2,5,8 thread3 将打印 3,6,9。我正在使用原子整数和模函数。

在第一个线程打印 1,4,7 而第二个线程打印 2,5,8 和第三个打印 3,6,9 的意义上,下面的实现工作正常,但问题是没有保持序列,即输出可能像 1, 3、2、4、5、7、8、6、9,而我希望保持顺序,因为适当的线程会打印这些值。 一个条件是我不想使用同步。 [仅用于学习目的]

import java.util.concurrent.atomic.AtomicInteger;

public class ThreeThreadsOrderedLockLess {

    AtomicInteger sharedOutput = new AtomicInteger(0);

    public static void main(String args[]) {



        ThreeThreadsOrderedLockLess t = new ThreeThreadsOrderedLockLess();



        ThreadTasks t1 = t.new ThreadTasks(0);
        ThreadTasks t2 = t.new ThreadTasks(1);
        ThreadTasks t3 = t.new ThreadTasks(2);

        Thread ts1 = new Thread(t1);
        Thread ts2 = new Thread(t2);
        Thread ts3 = new Thread(t3);
        ts1.start();
        ts2.start();
        ts3.start();

    }

    private class ThreadTasks implements Runnable {

        private final int threadPosition;


        public ThreadTasks(int threadPosition) {
            super();

            this.threadPosition = threadPosition;
        }

        @Override
        public void run() {

            while (sharedOutput.get() < 9) {

                if (sharedOutput.get() % 3 == this.threadPosition) {

                    System.out.println("Printing output for Thread: "
                            + this.threadPosition + "  "
                            + sharedOutput.incrementAndGet());
                }
            }

        }
    }

}

【问题讨论】:

  • 如果你不使用某种形式的同步,那么当然会发生这种情况!
  • 如果你想要串行行为,不要使用线程。
  • @Eyal:正如我提到的,应保持正确的顺序,即输出应为 1、2、3、4、5、6、7、8、9。

标签: java multithreading


【解决方案1】:

下面的代码 sn-p 将按顺序打印数字,所有线程将在任务完成后优雅地终止。 使用 AtomicInteger,它对于打印数字是线程安全的,并且可以应用相同的逻辑来打印,直到具有任意数量的线程的任意数字。

导入 java.util.concurrent.atomic.AtomicInteger; 公共类 PrintNumSequence { 公共静态无效主要(字符串 [] 参数) { AtomicInteger atomicInteger = new AtomicInteger(0); new NumPrinter(atomicInteger, 0).start();// thread0 new NumPrinter(atomicInteger, 1).start();// thread1 new NumPrinter(atomicInteger, 2).start();// thread2 } } 类 NumPrinter 扩展线程 { 私有 AtomicInteger atomicInteger; 私有 int 线程数; 公共NumPrinter(AtomicInteger atomicInteger,int threadNum) { this.atomicInteger = atomicInteger; this.threadNum = 线程数; } @覆盖 公共无效运行() { int num = atomicInteger.intValue(); 做 { 同步(atomicInteger) { 数 = atomicInteger.intValue(); // 如果数字是 9 则停止。 如果(数字 > 9) { atomicInteger.notifyAll(); 休息; } // 3 是线程数 if ((num % 3) == threadNum) { System.out.println("线程-" + threadNum + " -->" + num); num = atomicInteger.incrementAndGet(); } atomicInteger.notifyAll(); 尝试 { atomicInteger.wait(); } 捕捉(InterruptedException e) { e.printStackTrace(); } } } 而(真); } }

【讨论】:

    【解决方案2】:

    你应该先打印,然后递增:

    int value = sharedOutput.get() + 1;
    System.out.println("Printing output for Thread: "
                            + this.threadPosition + "  "
                            + value);
    sharedOutput.incrementAndGet();
    

    也就是说,所有线程都忙于循环,这将导致 100% 的 CPU 使用率。您应该改为同步线程。

    【讨论】:

    • 完美。很适合我。
    • 在 sysout 中直接使用 incrementAndGet() 有何不同?
    • 原代码中调用了incrementAndGet()。然后将返回的值与输出消息的其余部分连接起来。然后只打印消息。因此,在另一个线程看到 AtomicInteger 的新值的消息的增量和打印之间有很长的时间。
    • 一时间我也是这么想的。但是 incrementAndGet() 不是原子的吗?
    • 是的,它是原子的,那又怎样?它仍然在执行打印之前执行。所以其他线程看到新值,可以在第一个线程之前打印他们的行。
    【解决方案3】:

    这是因为每个线程的时间片由操作系统决定。因此,线程 x 可能会增加共享编号,但在打印之前,时间片会传递给下一个线程 y,后者现在读取共享编号并在递增后打印它(假设线程 y 比线程 x 获得更多时间来增加和打印共享号码) .

    【讨论】:

      【解决方案4】:

      使用 Java 的 wait()、notify()、notifyall() 方法。
      你也可以看看这些方法的Tutorial

      希望这将有助于解决您的问题。 . .

      这个例子的输出如下。

      放置:1
      得到:1
      放:2
      得到:2
      放:3
      得到:3
      放:4
      得到:4
      放:5
      得到:5

      【讨论】:

      • 我已经说过我不想使用同步!所以没有锁意味着等待通知不在画面中。
      【解决方案5】:

      这应该可行:

      package com.sid;
      
      import java.util.concurrent.atomic.AtomicInteger;
      
      public class NumberSequence {
      
          private AtomicInteger sharedOutput = new AtomicInteger(0);
          private Object object = new Object();
      
          public static void main(String args[]) {
      
              NumberSequence t = new NumberSequence();
      
              ThreadTasks t1 = t.new ThreadTasks(0);
              ThreadTasks t2 = t.new ThreadTasks(1);
              ThreadTasks t3 = t.new ThreadTasks(2);
      
              Thread ts1 = new Thread(t1);
              Thread ts2 = new Thread(t2);
              Thread ts3 = new Thread(t3);
      
              ts1.start();
              ts2.start();
              ts3.start();
      
          }
      
          private class ThreadTasks implements Runnable {
      
              private final int threadPosition;
      
              public ThreadTasks(int threadPosition) {
                  super();
      
                  this.threadPosition = threadPosition;
              }
      
              @Override
              public void run() {
      
                  while (sharedOutput.get() < 10) {
      
                      synchronized (object) {
      
                          if (sharedOutput.get() % 3 == this.threadPosition) {
      
                              if(sharedOutput.get() < 10)
                              System.out.println("Printing output for Thread: "
                                      + this.threadPosition + "  "
                                      + sharedOutput.incrementAndGet());
                          }
                      }
                  }
      
              }
          }
      
      }
      

      【讨论】:

      • 能否请您详细说明您的答案,添加更多关于您提供的解决方案的描述?
      【解决方案6】:

      适当的同步将帮助您获得明确的答案。我已经改进了实现,你应该解决你的问题。

          int threadId;
          int moduluos;
          int numOfThreads;
      
          public ThreadTasks(int id, int nubOfThreads) {
              threadId = id;
              this.numOfThreads = nubOfThreads;
              moduluos = threadId%numOfThreads;
          }
      
          public void run() {
              print();
          }
      
          private void print() {
              try {
                  while (true) {
                      synchronized (monitor) {
                          if (number.get() % numOfThreads != moduluos) {
                              monitor.wait();
                          } else {
                              System.out.println("ThreadId [" + threadId
                                      + "] printing -->"
                                      + number.getAndIncrement());
                              monitor.notifyAll();
                          }
                      }
                  }
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      
      }
      

      【讨论】:

        【解决方案7】:
            package test.mk.thread;
        import java.util.concurrent.atomic.AtomicInteger;
        
        public class MkThread2 {
            int nextThreadToRun = 1;
            int[] arr = {1,2,3,4,5,6,7,8,9,10,11};
            AtomicInteger nextArrayIndex = new AtomicInteger(0);
            boolean token = true;
        
            public static void main(String[] args) {
                MkThread2 mkThread = new MkThread2();
                Thread t1 = new Thread(new Worker2(1, mkThread));
                Thread t2 =  new Thread(new Worker2(2, mkThread));
                Thread t3 =  new Thread(new Worker2(3, mkThread));
                t1.start();
                t2.start();
                t3.start();
            }
        }
        
        
        class Worker2 implements Runnable{
            volatile int threadNo;
            private MkThread2 mkThread;
            private String threadName;
        
            Worker2(int threadNo, MkThread2 mkThread){
                this.threadNo = threadNo;
                this.mkThread = mkThread;
                this.threadName = "Thread:"+threadNo ;
            }
        
            public void run(){
                try{
                    synchronized (mkThread) {
                        while(mkThread.token){
                            while(threadNo != mkThread.nextThreadToRun){
                                mkThread.wait();
                            }
                            if(mkThread.token){//double checking
                                System.out.print(threadName+ "->" + mkThread.arr[mkThread.nextArrayIndex.get()]);
                                if(threadNo == 3) System.out.println();
                                mkThread.nextThreadToRun = getNextThread(threadNo);
                                if(mkThread.nextArrayIndex.get() == mkThread.arr.length-1){
                                    mkThread.token = false;
                                }
                                mkThread.nextArrayIndex.incrementAndGet();
                            }
                            mkThread.notifyAll();
        
                        }
                    }
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
        
            private int getNextThread(int threadNo){
                int result = -1;
                switch (threadNo) {
                case (1):
                    result = 2;
                    break;
                case (2):
                    result = 3;
                    break;
                case (3):
                    result = 1;
                    break;
                }
                return result;
            }
        }
        

        【讨论】:

          【解决方案8】:
          import java.util.concurrent.atomic.AtomicInteger; 
           public class Print123456789 {
          
          public static void main(String[] args) {
              print p1 = new print(0);
              print p2 = new print(1);
              print p3 = new print(2);
          
              Thread t1 = new Thread(p1);
              Thread t2 = new Thread(p2);
              Thread t3 = new Thread(p3);
          
              t1.start();
              t2.start();t3.start();
          
          
          }
          
          }
          
          
          
          class print implements Runnable {
          private int threadNumber;
          private static AtomicInteger atomicInteger = new AtomicInteger(0);
          public print(int threadNumber) {
              super();
              this.threadNumber = threadNumber;
          }
          
          public void run(){
              try{
              while(atomicInteger.get() < 10){
                  synchronized (atomicInteger) {
          
                      if((atomicInteger.get()%3) == this.threadNumber){
                          System.out.println(atomicInteger.getAndIncrement() + " Thread :" + this.threadNumber );
                          atomicInteger.notifyAll();
                          }
                      else
                          atomicInteger.wait();
                  }
              }
              }catch(InterruptedException e)
              {
                  e.printStackTrace();
              }
          }
          
          
          }
          

          【讨论】:

            【解决方案9】:

            使用阻塞队列可以更好地实现这一点。定义一个持有阻塞队列的工作者。工作人员在队列中等待,直到它收到一个数字。它打印它收到的数字,增加它并将它传递给链中的下一个工人。请参阅here 以获得完整的解决方案。

            【讨论】:

              【解决方案10】:
              package threeThread;
              
              class Task implements Runnable {
              
                String message;
                ThreeThread lock;
                int i = 0;
                int p;
              
                public Task(String text, ThreeThread obj, int p) {
                  message = text;
                  this.lock = obj;
                  this.p = p;
                }
              
                @Override
                public void run() {
              
                  while(true) {
                      synchronized (lock) {
              
                          while(!((lock.status % 3) == 0) && p == 1){
                              try {
                                  lock.wait();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
              
                          while(!((lock.status % 3) == 1) && p == 2){
                              try {
                                  lock.wait();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
              
                          while(!((lock.status % 3) == 2) && p == 3){
                              try {
                                  lock.wait();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
                          System.out.println("thread: " + p + " : " + message);
                          lock.status++;
                          lock.notifyAll();
                      }
                  }
                }
              }
              
              public class ThreeThread {
              
                volatile int status = 0;
                public static void main(String[] args) {
              
                  ThreeThread lock = new ThreeThread();
                  Thread t1 = new Thread(new Task("Hello", lock,1));
                  Thread t2 = new Thread(new Task("Good", lock,2));
                  Thread t3 = new Thread(new Task("Morning", lock,3));
                  t1.start();
                  t2.start();
                  t3.start();
                }
              
              }
              

              【讨论】:

                【解决方案11】:

                我正在使用 5 个线程打印 1-100 的代码。可以使用任意数量的线程以循环方式打印输出。

                基本概念是锁定一个对象并通知另一个对象执行打印值。

                public class PrintOneToHundredUsing5Threads {
                
                    public static void main(String[] args) {
                        List<Object> objList = new ArrayList<>();
                        for (int i = 0; i < 5; i++) {
                            objList.add(new Object());
                        }
                        for (int i = 0; i < 5; i++) {
                            Thread t = new Thread(new PrintThread(objList.get(i), objList.get((i + 1) % 5)));
                            t.setName("Thread" + i);
                            t.start();
                        }
                    }
                
                }
                
                class PrintThread implements Runnable {
                    Object current;
                    Object next;
                    volatile static int i = 1;
                
                    PrintThread(Object cur, Object next) {
                        this.current = cur;
                        this.next = next;
                    }
                
                    @Override
                    public void run() {
                        for (; i <= 100;) {
                            synchronized (current) {
                                synchronized (next) {
                                    next.notify();
                                    System.out.println(Thread.currentThread().getName() + " Value : " + i++);
                                }
                                try {
                                    current.wait();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                
                            }
                        }
                    }
                
                }
                

                【讨论】:

                  【解决方案12】:

                  您可以使用以下代码使用多个线程打印序列号 -

                  import java.util.ArrayList;
                  import java.util.List;
                  import java.util.concurrent.ArrayBlockingQueue;
                  import java.util.concurrent.BlockingQueue;
                  
                  public class ThreadCall extends Thread {
                  
                      private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
                      private ThreadCall next;
                  
                      public void setNext(ThreadCall t) {
                          this.next = t;
                      }
                  
                      public void addElBQ(int a) {
                          this.bq.add(a);
                      }
                  
                      public ThreadCall(String name) {
                          this.setName(name);
                      }
                  
                      @Override
                      public void run() {
                          int x = 0;
                          while(true) {
                              try {
                                  x = 0;
                                  x = bq.take();
                                  if (x!=0) {
                                      System.out.println(Thread.currentThread().getName() + " =>" + x);
                                      if (x >= 100) System.exit(0); // Need to stop all running threads
                                      next.addElBQ(x+1);
                                  }
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
                      }
                  
                      public static void main(String[] args) {
                          int THREAD_COUNT = 10;
                          List<ThreadCall> listThread = new ArrayList<>();
                  
                          for (int i=1; i<=THREAD_COUNT; i++) {
                              listThread.add(new ThreadCall("Thread " + i));
                          }
                  
                          for (int i = 0; i < listThread.size(); i++) {
                              if (i == listThread.size()-1) {
                                  listThread.get(i).setNext(listThread.get(0));
                              }
                              else listThread.get(i).setNext(listThread.get(i+1));
                          }
                  
                          listThread.get(0).addElBQ(1);
                  
                          for (int i = 0; i < listThread.size(); i++) {
                              listThread.get(i).start();
                          }
                      }
                  }
                  

                  希望这能解决您的问题。

                  【讨论】:

                    【解决方案13】:
                    public class PrintThreadsInSerial {
                        public static void main(String[] args) {
                        Thread t = new Thread(new Job());
                        t.start();
                        }
                    }
                    
                    class Job implements Runnable {
                        @Override
                        public void run() {
                         while (true) {
                            for (int i = 1; i <= 3; i++) {
                             System.out.println(i);
                            }
                         }
                        }
                    }
                    

                    【讨论】:

                      【解决方案14】:

                      ThreadSynchronization 类可用于打印“n”号之间的数字。线程的顺序。 逻辑是在每个连续线程之间创建一个公共对象,并使用“等待”、“通知”来按顺序打印数字。 注意:最后一个线程将与第一个线程共享一个对象。

                      您可以在运行程序之前更改“maxThreads”值以增加或减少程序中的线程数。

                      import java.util.ArrayList;
                      import java.util.List;
                      
                      public class ThreadSynchronization {
                      
                          public static int i = 1;
                          public static final int maxThreads = 10;
                      
                          public static void main(String[] args) {
                              List<Object> list = new ArrayList<>();
                              for (int i = 0; i < maxThreads; i++) {
                                  list.add(new Object());
                              }
                              Object currObject = list.get(maxThreads - 1);
                              for (int i = 0; i < maxThreads; i++) {
                                  Object nextObject = list.get(i);
                                  RunnableClass1 a = new RunnableClass1(currObject, nextObject, i == 0 ? true : false);
                                  Thread th = new Thread(a);
                                  th.setName("Thread - " + (i + 1));
                                  th.start();
                                  currObject = list.get(i);
                              }
                          }
                      
                      }
                      
                      class RunnableClass implements Runnable {
                      
                          private Object currObject;
                          private Object nextObject;
                          private boolean firstThread;
                      
                          public RunnableClass(Object currObject, Object nextObject, boolean first) {
                              this.currObject = currObject;
                              this.nextObject = nextObject;
                              this.firstThread = first;
                          }
                      
                          @Override
                          public void run() {
                              int i = 0;
                              try {
                                  if (firstThread) {
                                      Thread.sleep(5000);
                                      firstThread = false;
                                      System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                                      synchronized (nextObject) {
                                          nextObject.notify();
                                      }
                                  }
                                  while (i++ < Integer.MAX_VALUE) {
                                      synchronized (currObject) {
                                          currObject.wait();
                                      }
                                      System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                                      Thread.sleep(1000);
                                      synchronized (nextObject) {
                                          nextObject.notify();
                                      }
                                  }
                              } catch (Exception e) {
                                  e.printStackTrace();
                              }
                          }
                      }
                      

                      【讨论】:

                        【解决方案15】:
                        public class PrintSeqNumUsingAltThreads {
                        
                            public static void main(String[] args) {
                                AtomicInteger counter = new AtomicInteger(0);
                                int numThreads = 3;
                        
                                Thread t1 = new Thread(new SeqNumPrinter(counter, 0, numThreads));
                                Thread t2 = new Thread(new SeqNumPrinter(counter, 1, numThreads));
                                Thread t3 = new Thread(new SeqNumPrinter(counter, 2, numThreads));
                        
                                t1.currentThread().setName("T1");
                                t2.currentThread().setName("T2");
                                t3.currentThread().setName("T3");
                        
                                t1.start();
                                t2.start();
                                t3.start();
                            }
                        }
                        
                        
                        public class SeqNumPrinter implements Runnable {
                        
                            AtomicInteger atmCounter;
                            Integer threadPosition;
                            Integer numThreads;
                        
                            public SeqNumPrinter(AtomicInteger counter, int position, int numThreads) {
                                this.atmCounter = counter;
                                this.threadPosition = position;
                                this.numThreads = numThreads;
                            }
                        
                            @Override
                            public void run() {
                                while (atmCounter.get() < 10) {
                                    if (atmCounter.get() % numThreads == threadPosition) {
                                        System.out.println("Printing value : " + atmCounter.getAndIncrement() + ", by thread : " + 
                                                Thread.currentThread().getName());
                                    }
                                }
                            }
                        }
                        

                        输出:

                        打印值:0,按线程:Thread-0
                        打印值:1,按 线程:Thread-1
                        打印值:3,按线程:Thread-0
                        打印值:2,按线程:Thread-2
                        打印值:4,按 线程:Thread-1
                        打印值:6,按线程:Thread-0
                        打印值:5,按线程:Thread-2
                        打印值:7,按 线程:Thread-1
                        打印值:9,按线程:Thread-0
                        打印值:8,按线程:Thread-2

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2019-11-05
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2018-05-03
                          相关资源
                          最近更新 更多