【问题标题】:How to start two process at the same time and then wait both completed?如何同时启动两个进程然后等待都完成?
【发布时间】:2013-12-13 20:47:51
【问题描述】:

我想同时启动两个进程,并确保在继续其他步骤之前完成所有进程。你能帮我吗?我已经尝试过Thread,它不能同时启动两个并等到完成。

    final CyclicBarrier gate = new CyclicBarrier(3);
    Thread r2 = new Thread()
    {

        public void run()
        {
            try
            {
                int i = 0;
                while (i < 3)
                {
                    System.out.println("Goodbye, " + "cruel world!");
                    Thread.sleep(2000L);
                    i++;
                    gate.await();
                }
            }
            catch (InterruptedException | BrokenBarrierException iex)
            {
            }
        }
    };

    Thread r3 = new Thread()
    {
        public void run()
        {
            try
            {
                int i = 0;
                while (i < 3)
                {
                    System.out.println("Goodbye, " + "cruel world!");
                    Thread.sleep(2000L);
                    i++;
                    gate.await();
                }
            }
            catch (InterruptedException | BrokenBarrierException iex)
            {
            }
        }
    };

    r2.start();
    r3.start();
    gate.await();
    System.out.println("Donew");

【问题讨论】:

  • 请展示您所做的研究以及您尝试过的内容。谢谢。
  • 你说你已经尝试过使用Thread。你能告诉我们你试验过的代码吗?这将使您更清楚地尝试过什么以及(如果您解释的话)您想要实现什么。

标签: java concurrency


【解决方案1】:

您可以使用Thread.join() 等待子进程/线程完成。 你不应该需要CyclicBarrier

【讨论】:

    【解决方案2】:

    你的问题是你在反复等待三方,但只有两个线程在反复调用await()。我希望您的代码立即打印出“再见,残酷的世界!”两次,然后“完成”,然后挂起,因为循环正在等待第三个线程再次调用await(),但主线程现在已经终止。

    一种解决方案是让您的主线程循环,调用await() 的次数与您的任务执行的次数相同。但这会有点丑陋。

    我建议使用ExecutorServiceinvokeAll() 方法。这将在(大约)同一时间将您的任务提交给服务,然后阻塞直到所有任务完成。如果您想尝试提高任务开始的同时性,可以添加CyclicBarrier,但看起来您更关心任务何时结束,invokeAll() 会为您处理。

    final class Sample
      implements Callable<Void>
    {
    
      private static final int ITERATIONS = 3;
    
      private static final long AVG_TIME_MS = 2000;
    
      public static void main(String[] args)
        throws InterruptedException
      {
        List<Sample> tasks = Arrays.asList(new Sample(), new Sample());
        ExecutorService workers = Executors.newFixedThreadPool(tasks.size());
        for (int i = 1; i <= ITERATIONS; ++i) {
          /* invokeAll() blocks until all tasks complete. */
          List<Future<Void>> results = workers.invokeAll(tasks);
          for (Future<?> result : results) {
            try {
              result.get();
            }
            catch (ExecutionException ex) {
              ex.getCause().printStackTrace();
              return;
            }
          }
          System.out.printf("Completed iteration %d.%n", i);
        }
        workers.shutdown();
        System.out.println("Done");
      }
    
      @Override
      public Void call()
        throws InterruptedException
      {
        /* The average wait time will be AVG_TIME_MS milliseconds. */
        ThreadLocalRandom random = ThreadLocalRandom.current();
        long wait = (long) (-AVG_TIME_MS * Math.log(1 - random.nextDouble()));
        System.out.printf("Goodbye, cruel world! (Waiting %d ms)%n", wait);
        Thread.sleep(wait);
        return null;
      }
    
    }
    

    请注意我是如何通过随机等待时间来增加趣味性的。然而,invokeAll() 一直等到该迭代中的所有任务完成。

    【讨论】:

    • Thread.join() 是要走的路。就我的口味而言,在这种情况下,CyclicBarrier 有点过于沉重。
    • 我们真的不知道是什么情况。如果任务被重复执行,CyclicBarrier 可能会很有用。仅仅为了join() 方法的方便而创建新线程可能是一种浪费。
    【解决方案3】:
    1. 单处理器机器是不可能的。
    2. 即使您在线程上找到很多答案,它也不会同时启动两个进程
    3. 如果您接受Relative Simultanity,那就很容易了。

    【讨论】:

    • OP 没有提到有多少处理器。尽管这在技术上可能是正确的,但对于应用程序来说,很容易让事情似乎同时发生,即使在单个处理器上也是如此。无论如何,它并没有解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 2011-10-07
    • 1970-01-01
    • 2010-10-11
    • 2012-02-15
    相关资源
    最近更新 更多