【问题标题】:Print RED BLUE GREEN in order using System.out.print使用 System.out.print 按顺序打印 RED BLUE GREEN
【发布时间】:2013-09-03 11:43:33
【问题描述】:
public class CyclicBar {
    private final static CyclicBarrier cb = new CyclicBarrier(3,
            new Runnable() {
                @Override
                public void run() {
                    System.out.println("\n-------------");
                }
            });

    public static void main(String[] args) {

        final class ColouredRunnable implements Runnable {
            private int i;

            public ColouredRunnable(int j) {
                this.i = j;
            }

            @Override
            public void run() {
                final String name = Thread.currentThread().getName();
                while (true) {
                    cyclicAwait();
                    for (int i = 0; i < name.length(); i++) {
                        sleep();
//                      System.out.print("" + name.charAt(i) + this.i + " ");
                        System.out.print("" + name.charAt(i) +  " ");
                    }
                }
            }
        }
        ;

        int i = 0;
        new Thread(new ColouredRunnable(i++), "RED").start();
        new Thread(new ColouredRunnable(i++), "BLUE").start();
        new Thread(new ColouredRunnable(i++), "GREEN").start();
    }

    private static int cyclicAwait() {
        try {
            return cb.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return -1;
    }

    private static void sleep() {
        try {
            Thread.sleep(ThreadLocalRandom.current().nextLong(200, 600));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

上面的代码当前打印

-------------
G R B R E L E E D U E N 
-------------
B R G E R L U E D E E N 
-------------
R G B E L R E U D E E N 
-------------
R G B E R L U E D E E N 
-------------
B R G E L D R U E E E N 
-------------

如何更改上述代码并在适当的位置添加适当的屏障以产生以下输出

-------------
R E D B L U E G R E E N 
-------------
R E D B L U E G R E E N 
-------------
R E D B L U E G R E E N 

约束

  • 必须使用现代 java 并发高级对象之一
  • 不应使用隐式锁定synchronisedwaitnotify
  • 必须使用 System.out.print() 打印单个字符
  • 使用 3 个线程,每个线程必须打印其名称(颜色)
  • 应该按照RED BLUE GREEN的顺序打印

【问题讨论】:

  • 确切的问题是它没有按顺序打印
  • 你可以在前一个线程结束的时候开始下一个线程
  • 将每个线程作为一个变量并使用 thead_name.join() 等待每个线程完成。然后,再写一个线程。
  • 看起来您需要自定义同步器。
  • 目标是始终打印 REDBLUEGREEN,还是应该能够以任何顺序打印颜色(只要字母没有混淆)?

标签: java multithreading concurrency synchronization java.util.concurrent


【解决方案1】:
    public class TestSynMain {
    private final static AbstractQueuedSynchronizer cb = new TestSynchronizer(6);

    public static void main(String[] args) {

        final class ColouredRunnable implements Runnable {
            private String color;

            public ColouredRunnable(String color) {
                this.color = color;
            }

            @Override
            public void run() {
                while (true) {
                    try {
                        boolean result = false;
                        do{
                             result = cb.tryAcquireNanos(Integer.parseInt(Thread.currentThread().getName()), TimeUnit.MILLISECONDS.toNanos(1000));
                        }while(!result);

                        for (int i = 0; i < color.length(); i++) {
                            try {
                                Thread.sleep(300);
                            } catch (InterruptedException e) {
                                System.exit(-1);
                            }
                            System.out.print("" + color.charAt(i) +  " ");
                        }
                    } catch (NumberFormatException e1) {
                        e1.printStackTrace();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }finally{
                        cb.release(Integer.parseInt(Thread.currentThread().getName()));
                    }
                }
            }
        }

        new Thread(new ColouredRunnable("RED"), "0").start();
        new Thread(new ColouredRunnable("BLUE"), "1").start();
        new Thread(new ColouredRunnable("GREEN"), "2").start();
        new Thread(new ColouredRunnable("BLACK"), "3").start();
        new Thread(new ColouredRunnable("MAGENTA"), "4").start();
        new Thread(new ColouredRunnable("WHITE"), "5").start();
    }
}

public class TestSynchronizer extends AbstractQueuedSynchronizer{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    int count;

    public TestSynchronizer(int count) {
        this.count = count;
        setState(0);
    }


    @Override
    protected boolean tryAcquire(int arg) {
        if(arg == getState()){
            System.out.println("Acquires" + Thread.currentThread().getName());
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }

    @Override
    protected boolean tryRelease(int arg) {
        int state = getState();
        setState(++state % count);
        setExclusiveOwnerThread(null);
        return true;
    }


}

如何使用?

Synchronizer 接受一个参数count,即最多需要同步多少线程。

线程的名称必须是他们需要采取的顺序。现在您可以根据需要添加任意数量的线程。

我设计了一个自定义Synchronizer 并用它来定义一个允许锁定和解锁线程的新策略。

【讨论】:

    【解决方案2】:

    如果你想和他们一起玩的话,Phasers 也很酷。所有这一切都需要您在words 列表中填充您想要的任何单词 - 它为每个单词创建一个线程并且它们都很好玩。

    public class PhaserTest
    {
        private final Phaser phaser = new Phaser(1) {
            protected boolean onAdvance(int phase, int parties)
            {
                //Phaser version of your CyclicBarrier Runnable
                if(parties == 1)
                    System.out.println("\n-------------");
                return false;
            }
        };
    
        public void runTest()
        {
            List<String> words = Arrays.asList("RED", "BLUE", "GREEN");
    
            for(int i = 0; i < words.size();i++)
                new Thread(new ColouredRunnable(words.get(i),i + 1)).start();
    
            while(phaser.arriveAndAwaitAdvance() != (words.size() + 1)){}
            System.out.println("Done.");
        }
    
        public class ColouredRunnable implements Runnable {
            private final int order;
            private final String color;
    
            public ColouredRunnable(String s, int order) {
                this.color = s;
                this.order = order;
                phaser.register();
            }
    
            @Override
            public void run() {
                while(phaser.arriveAndAwaitAdvance() != order){}
    
                for (int i = 0; i < color.length(); i++) {
                    sleep();
                    System.out.print("" + color.charAt(i) +  " ");
                }
                phaser.arriveAndDeregister();
            }
    
            private void sleep() {
                try {
                    Thread.sleep(ThreadLocalRandom.current().nextLong(200, 600));
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      此解决方案使用 3 个循环障碍。代码最初使用循环屏障在线程之间创建托管死锁。通过在main 线程中触发cb[cb.length-1].await(); 来打破死锁

      public static void main(String[] args) {
          String colors[] = { "RED", "BLUE", "GREEN" };
          final CyclicBarrier[] cb = createCB(colors);
      
          for (int i = 0; i < colors.length; i++) {
              final int j = i;
      
              new Thread(colors[i]) {
                  public void run() {
                      while (true) {
                          try {
                              cb[(j == 0 ? cb.length : j) - 1].await();// Wait for
                                                                          // previous
                                                                          // barrier
                              String name = getName();
                              for (int i = 0; i < name.length(); i++) {
                                  CyclicBari.sleep();
                                  System.out.print(" " + name.charAt(i) + " ");
                              }
                              cb[j].await();// Notify next
                          } catch (InterruptedException | BrokenBarrierException e) {
                              e.printStackTrace();
                          }
                      }
                  }
      
              }.start();
          }
      
          System.out.println("start");
          try {
              cb[cb.length-1].await();
          } catch (InterruptedException | BrokenBarrierException e) {
              e.printStackTrace();
          }
      
      }
      
      private static void sleep() {
          try {
              Thread.sleep(ThreadLocalRandom.current().nextLong(200, 600));
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
      
      private static CyclicBarrier[] createCB(String[] colors) {
          final CyclicBarrier cb[] = new CyclicBarrier[colors.length];
          for (int i = 0; i < cb.length; i++) {
              final int j = i;
              cb[i] = new CyclicBarrier(2, new Runnable() {
      
                  @Override
                  public void run() {
                      if (j == cb.length - 1) {
                          System.out.println("\n-------------");
                      } else {
                          System.out.print(".");
                      }
                  }
              });
      
          }
          return cb;
      }
      

      输出

      -------------
       R  E  D . B  L  U  E . G  R  E  E  N 
      -------------
       R  E  D . B  L  U  E . G  R  E  E  N 
      -------------
       R  E  D . B  L  U  E . G  R  E  E  N 
      -------------
      

      【讨论】:

        猜你喜欢
        • 2021-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-03
        相关资源
        最近更新 更多