Java线程等待值

标签 java multithreading wait

我有以下情况:

为了运行一个算法,我必须运行多个线程,每个线程都将在它结束之前设置一个实例变量 x。问题是这些线程不会立即返回:

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 循环并检查是否终止?

谢谢大家!

最佳答案

创建一些共享存储来保存每个线程的 x 值,或者如果足够的话只存储总和。使用 CountDownLatch等待线程终止。每个线程在完成后将调用 CountDownLatch.countDown()并且您的 myAlgorithm 方法将使用 CountDownLatch.await()等待他们的方法。

编辑:这是我建议的方法的完整示例。它创建了 39 个工作线程,每个工作线程将一个随机数添加到一个共享总和中。当所有 worker 都完成后,计算并打印平均值。

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 , 和 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线程等待值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7811681/

相关文章:

c# - 从线程向主线程发送异常?

java - Android:尝试在两个动画之间添加等待,在 wait() 错误之前获取对象未被线程锁定

java - Telnet Apache Commons NET 打印垃圾字符

java - 导入 com.sun.javadoc,与 Eclipse 和 Ant 一起使用

c# - .NET 后台线程如何检测到主应用程序正在关闭?

c++ - 从另一个非进程和日志堆栈发送信号到线程没有发生

java - 如何在任意数量的空格上拆分字符串,同时保留所有空格?

java - 除了java反射api之外,是否有更好的方法来获取对象的字段 getter ,或者我滥用了PropertyDescriptor的getReadMethod?

ios - 如何在没有超时错误的情况下在 XCTest 中等待 T 秒?

jquery 在另一个完成后运行自定义函数