所有子线程完成执行后如何运行主线程

时间:2015-01-27 07:03:41

标签: java multithreading inner-classes anonymous-class

我有一个要求,其中28个线程必须完成某些功能。我在匿名内部类中创建了这些线程,如:

Thread t=new Thread(new Runnable(){public void run() 
                        {//code
                        }}
                                );

                        t.start();

现在我想要在所有这些线程完成工作后开始进一步的执行。

注意:我对join()方法感到困惑,因为它使我的线程顺序运行。

所以任何人都可以建议我,一旦这些线程完成工作,我怎么能让主线程运行。

5 个答案:

答案 0 :(得分:6)

  

注意:我对join()方法感到困惑,因为它使我的线程按顺序运行。

如果您有这样的代码,它会这样做:

for (Runnable runnable : runnables) {
    Thread t = new Thread(runnable);
    t.start();
    t.join();
}

但是,您可以启动要并行运行的所有线程,然后在它们上面调用join。例如:

List<Thread> threads = new ArrayList<>();
for (Runnable runnable : runnables) {
    Thread t = new Thread(runnable);
    t.start();
    threads.add(t);
}
// Now everything's running - join all the threads
for (Thread thread : threads) {
     thread.join();
}

// Now you can do whatever you need to after all the
// threads have finished.

当然还有许多其他方法 - 直接启动线程可能不适合在代码中使用更高级别的抽象;这取决于你想要实现的目标。以上情况应该可以正常工作 - 假设所有Runnable能够并行运行而不会通过同步相互阻塞。

答案 1 :(得分:2)

使用CountDownLatch并等待所有线程完成。 :)。

PS:我同意,使用join()也是正确且更有效的。

示例代码:

public static void main(String [] args)抛出InterruptedException {         线程t1 =新线程(新的Runnable(){

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("t1 : " + i);
            }

        }
    });
    t1.start();
    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("t2 : " + i);
            }

        }
    });
    t2.start();
    t1.join();
    t2.join();
    System.out.println("main");

}

O / P:

t1 : 0
t1 : 1
t2 : 0
t1 : 2
t1 : 3
t2 : 1
t1 : 4
t1 : 5
t2 : 2
t1 : 6
t1 : 7
t2 : 3
t1 : 8
t1 : 9
t2 : 4
t2 : 5
t2 : 6
t2 : 7
t2 : 8
t2 : 9
main

答案 2 :(得分:2)

利用CountDownLatch

public static void main(String... args) {
    final CountDownLatch latch = new CountDownLatch(28);
    for(int i=0;i<28;i++) {
        Thread t=new Thread(new Runnable(){
                        public void run() 
                        {
                            try {
                                //code
                            } finally {
                                latch.countDown();
                            }
                        }
        });

        t.start();

    }
    latch.await();
    // Continue Code
}

答案 3 :(得分:1)

根据您加入的行为,我猜测您是在一个循环中开始加入线程。

如果你检查this page上的javadoc,你会注意到对join的调用将停止执行调用线程,直到另一个线程完成执行。

您可能希望在创建它们时保留一个数组或一个线程列表,并在一个循环中启动它们,然后才将它们全部加入。

Thread[] workers = new Thread[28];
for (int i = 0; i < workers.length; i++) {
    workers[i] = new Thread { ... };
}
// Start running all threads
for (Thread worker: workers) {
    worker.start();
}
// Make sure all threads are completed
for (Thread worker: workers) {
    worker.join(); // if the worker already stopped, it'll return immediately.
}
// Now all threads have finished running and you can start post-processing

这不是最优雅的解决方案,但它可以解决问题。 正如其他人所说,你应该使用CountDownLatch(尚未使用过,但我无法提供反馈)

编辑:我被Jon Skeet殴打,对不起多余的回答...

答案 4 :(得分:1)

CountDownLatch是更好的选择。

我创建了虚拟程序。 在这个程序中,我总和1000号。我创建了10个线程。在主线程中,我正在做所有子线程总和的圆顶。只需查看代码,您就会明白。

package Test1;

import java.util.concurrent.CountDownLatch;

class Sum extends Thread {
    private int from;
    private int to;
    private int sum = 0;
    CountDownLatch latch;

    public int getSum() {
        return sum;
    }

    public Sum(int from, int to, CountDownLatch latch) {
        this.from = from;
        this.to = to;
        this.latch = latch;
    }

    public void run() {
        for (int i = from; i < to; i++) {
            sum += i;
        }
        latch.countDown();
    }

}

public class Test5 {

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

        int n = 1000;
        int tn = 10;
        int from = 1;
        int to;
        int sum = 0;
        Sum[] sumArray = new Sum[tn];
        final CountDownLatch latch = new CountDownLatch(tn);
        for (int i = 0; i < tn; i++) {
            to = from + n / tn;
            Sum s = new Sum(from, to, latch);
            sumArray[i] = s;
            s.start();
            from = to;
        }

        // Thread.sleep(1000);
        latch.await();
        for (int i = 0; i < tn; i++) {
            sum += sumArray[i].getSum();
        }
        System.out.println(sum);
    }
}