Java线程等待值 [英] Java Threads waiting value
问题描述
我有以下情况:
为了运行算法,我必须运行多个线程,每个线程都会在它死之前设置一个实例变量x 。问题是这些线程不会立即返回:
In order to run a algorithm, i must run several threads and each thread will set a instance variable x, right before it dies. The problem is that these threads dont return immediately:
public Foo myAlgorithm()
{
//create n Runnables (n is big)
//start these runnables (may take long time do die)
//i need the x value of each runnable here, but they havent finished yet!
//get average x from all the runnables
return new Foo(averageX);
}
我应该使用等待通知吗?或者我应该嵌入一个while循环并检查终止?
Should i use wait notify ? Or should i just embed a while loop and check for termination ?
谢谢大家!
推荐答案
创建一些共享存储来保存 x
来自每个线程的值,或者只是存储总和(如果足够的话)。使用 CountDownLatch
等待线程终止。每个线程完成后,将调用 CountDownLatch.countDown()
并且您的 myAlgorithm
方法将使用< a href =http://download.oracle.com/javase/1,5,0/docs/api/java/util/concurrent/CountDownLatch.html#await%28%29 =nofollow> CountDownLatch.await()
等待它们的方法。
Create some shared storage to hold the x
value from each thread, or just store the sum if that's sufficient. Use a CountDownLatch
to wait for the threads to terminate. Each thread, when finished, would call CountDownLatch.countDown()
and your myAlgorithm
method would use the CountDownLatch.await()
method to wait for them.
编辑:这是我建议的方法的完整示例。它创建了39个工作线程,每个线程为共享总和添加一个随机数。完成所有工作后,计算并打印平均值。
Here's a complete example of the approach I suggested. It created 39 worker threads, each of which adds a random number to a shared sum. When all of the workers are finished, the average is computed and printed.
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
class Worker implements Runnable {
private final AtomicInteger sum;
private final CountDownLatch latch;
public Worker(AtomicInteger sum, CountDownLatch latch) {
this.sum = sum;
this.latch = latch;
}
@Override
public void run() {
Random random = new Random();
try {
// Sleep a random length of time from 5-10s
Thread.sleep(random.nextInt(5000) + 5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Compute x
int x = random.nextInt(500);
// Add to the shared sum
System.out.println("Adding " + x + " to sum");
sum.addAndGet(x);
// This runnable is finished, so count down
latch.countDown();
}
}
class Program {
public static void main(String[] args) {
// There will be 39 workers
final int N = 39;
// Holds the sum of all results from all workers
AtomicInteger sum = new AtomicInteger();
// Tracks how many workers are still working
CountDownLatch latch = new CountDownLatch(N);
System.out.println("Starting " + N + " workers");
for (int i = 0; i < N; i++) {
// Each worker uses the shared atomic sum and countdown latch.
Worker worker = new Worker(sum, latch);
// Start the worker
new Thread(worker).start();
}
try {
// Important: waits for all workers to finish.
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Compute the average
double average = (double) sum.get() / (double) N;
System.out.println(" Sum: " + sum.get());
System.out.println("Workers: " + N);
System.out.println("Average: " + average);
}
}
输出应该是这样的:
Starting 39 workers
Adding 94 to sum
Adding 86 to sum
Adding 454 to sum
...
...
...
Adding 358 to sum
Adding 134 to sum
Adding 482 to sum
Sum: 10133
Workers: 39
Average: 259.8205128205128
编辑:只是为了好玩,这是一个使用 ExecutorService
, Callable
和 未来
。
Just for fun, here is an example using ExecutorService
, Callable
, and Future
.
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
class Worker implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Random random = new Random();
// Sleep a random length of time, from 5-10s
Thread.sleep(random.nextInt(5000) + 5000);
// Compute x
int x = random.nextInt(500);
System.out.println("Computed " + x);
return x;
}
}
public class Program {
public static void main(String[] args) {
// Thread pool size
final int POOL_SIZE = 10;
// There will be 39 workers
final int N = 39;
System.out.println("Starting " + N + " workers");
// Create the workers
Collection<Callable<Integer>> workers = new ArrayList<Callable<Integer>>(N);
for (int i = 0; i < N; i++) {
workers.add(new Worker());
}
// Create the executor service
ExecutorService executor = new ScheduledThreadPoolExecutor(POOL_SIZE);
// Execute all the workers, wait for the results
List<Future<Integer>> results = null;
try {
// Executes all tasks and waits for them to finish
results = executor.invokeAll(workers);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
// Compute the sum from the results
int sum = 0;
for (Future<Integer> future : results) {
try {
sum += future.get();
} catch (InterruptedException e) {
e.printStackTrace(); return;
} catch (ExecutionException e) {
e.printStackTrace(); return;
}
}
// Compute the average
double average = (double) sum / (double) N;
System.out.println(" Sum: " + sum);
System.out.println(" Workers: " + N);
System.out.println(" Average: " + average);
}
}
输出应如下所示:
Starting 39 workers
Computed 419
Computed 36
Computed 338
...
...
...
Computed 261
Computed 354
Computed 112
Sum: 9526
Workers: 39
Average: 244.25641025641025
这篇关于Java线程等待值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!