2

我想要一个在不同线程中运行 2 个或更多方法的方法。我想确保在所有线程完成之前该方法不会完成。

4

4 回答 4

6

最好的方法是利用 Executor Service API 来管理线程池,而不是自己启动无限数量的线程。

ExecutorService pool = Executors.newCachedThreadPool();
for (Runnable r : new Runnable[] {
    new R() { void r() { myMethod1(); }},
    new R() { void r() { myMethod2(); }},
})
  pool.execute(r);
pool.shutdown();
pool.awaitTermination(60, TimeUnit.SECONDS);

abstract class R implements Runnable
  public final void run() { r(); }
  abstract void r();
}

请注意,坚持每个方法都在其自己的单独线程中运行是不可取的。线程是相当重量级的(每个都分配一个完整的调用堆栈),随着线程数的增加远远超过可用处理器内核的数量,性能实际上会降低。

于 2012-11-06T10:58:34.237 回答
2

我的解决方案是

功能:

public void runParallel(Runnable... runnables) throws InterruptedException {

List<Thread> threads = new ArrayList<Thread>(runnables.length);

for (Runnable runnable :runnables) {
    Thread th = new Thread(runnable);
    threads.add(th);
    th.start();
}

for (Thread th : threads) {
    th.join();
}

采用:

runParallel(new Runnable() {
                @Override
                public void run() {
                    method1()
                }
            }, new Runnable() {
                @Override
                public void run() {
                    method2()
                }
            }
);

有更好的主意吗?也许有一种我不知道的更短的方法;)

于 2012-11-06T10:53:06.440 回答
2

我更喜欢这样的东西:

public static void runParallel(Runnable... runnables) throws InterruptedException {
    final CountDownLatch done = new CountDownLatch(runnables.length);
    for (final Runnable r: runnables) {
        new Thread(new Runnable() {
             public void run() {
                 try {
                     r.run();
                 } finally {
                     done.countDown();
                 }
             }
        }).start();
    }
   done.await();
}

这种方法的一个优点是它也适用于线程池(即您可以替换new Thread(...).start()executor.submit(...))。

它还允许您使用预先存在的线程池,这与基于awaitTermination()强制您为每次调用创建新池的解决方案不同。

于 2012-11-06T11:00:01.100 回答
0

遵循damienix给出的 API :

public void runParallel(Runnable... runnables) throws InterruptedException {
    final ExecutorService pool = Executors.newFixedThreadPool(runnables.length);
    for (Runnable runnable: runnables) {
        pool.submit(runnable);
    }
    pool.shutdown();
    pool.awaitTermination(1, TimeUnit.MINUTES);
}
于 2012-11-06T11:00:05.453 回答