等待线程

时间:2010-04-05 19:42:35

标签: java multithreading wait

我有一个包含以下(Java)代码的方法:

doSomeThings();
doSomeOtherThings();

doSomeThings()创建一些线程,每个线程只运行一段有限的时间。问题是我不希望在doSomeOtherThings()启动的所有线程完成之前调用doSomeThings()。 (同样doSomeThings()将调用可能启动新线程的方法等等。我不想在所有这些线程完成之前执行doSomeOtherThings()。)

这是因为doSomeThings()myObject会将null设置为doSomeOtherThings(),而myObject.myMethod()会调用myObject而我不希望null那时候是{{1}}。

有没有一些标准的方法来做这种事情(在Java中)?

6 个答案:

答案 0 :(得分:10)

您可能需要查看java.util.concurrent包。特别是,您可以考虑使用

中的CountDownLatch
package de.grimm.game.ui;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

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

    final ExecutorService executor = Executors.newFixedThreadPool(5);
    final CountDownLatch latch = new CountDownLatch(3);

    for( int k = 0; k < 3; ++k ) {

        executor.submit(new Runnable() {
            public void run() {
                // ... lengthy computation...
                latch.countDown();
            }
        });
    }

    latch.await();

    // ... reached only after all threads spawned have
    // finished and acknowledged so by counting down the
    // latch.

    System.out.println("Done");
}
}

显然,如果您事先知道分叉线程的数量,这项技术才有效,因为您需要用该数字初始化锁存器。

另一种方法是使用条件变量,例如:

boolean done = false;

void functionRunInThreadA() {

    synchronized( commonLock ) {

        while( !done ) commonLock.wait();
    }

    // Here it is safe to set the variable to null
}

void functionRunInThreadB() {

    // Do something...

    synchronized( commonLock ) {
        done = true;
        commonLock.notifyAll();
    }
}

您可能需要添加异常处理(InteruptedException)等等。

答案 1 :(得分:6)

查看Thread.join()方法。

我不清楚你的确切实现,但似乎doSomeThings()应该在返回之前等待子线程。

在doSomeThings()方法内部,通过调用Thread.join()方法等待线程。

当你创建一个线程并调用该线程的join()方法时,调用线程会一直等到该线程对象死掉。

示例:

// Create an instance of my custom thread class
MyThread myThread = new MyThread();
// Tell the custom thread object to run
myThread.start();
// Wait for the custom thread object to finish
myThread.join();

答案 2 :(得分:3)

您正在寻找执行者服务并使用期货:)

请参阅http://java.sun.com/docs/books/tutorial/essential/concurrency/exinter.html

所以基本上收集你提交给执行者服务的所有runnables的期货。循环所有期货并调用get()方法。这些将在完成相应的runnable时返回。

答案 3 :(得分:1)

您可以使用的另一个有用的更强大的Synchronization Barrier与CountdownLatch类似的功能是CyclicBarrier。它类似于CountdownLatch,您必须知道正在使用多少方(线程),但它允许您重复使用屏障,因为每次都会创建一个新的CountdownLatch实例。

我确实喜欢momania建议使用ExecutorService,收集期货并调用所有这些直到他们完成。

答案 4 :(得分:0)

另一个选择是睡眠主线程,如果其他线程已经完成,请经常检查它。但是,我更喜欢Dirk和Marcus Adams的答案 - 只是为了完整起见而把它扔出去。

答案 5 :(得分:0)

取决于你在这里尝试做什么。您主要关心的是能否动态确定doSomeThings()内部调用的连续方法产生的各种线程,然后能够等到它们完成后再调用{{1 }?或者可以知道在编译时生成的线程?在后一种情况下,有许多解决方案,但所有这些解决方案基本上都涉及在所有这些线程上调用doSomeOtherThings()方法。

如果确实是前者,那么最好使用Thread.join()及其ThreadGroup 方法。如果您已经将新线程正确添加到ThreadGroup,这将为您提供由doSomeThings()生成的所有线程的数组。然后,您可以遍历返回数组中的所有线程引用,并在调用enumerate()之前在主线程上调用join()