当前位置: 首页 > 面试题库 >

Java线程等待值

容远
2023-03-14
问题内容

我有以下情况:

为了运行算法,我必须运行多个线程,并且每个线程都会在死之前设置一个实例变量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每个线程的值,或者如果足够的话,只存储总和。使用a
CountDownLatch等待线程终止。每个线程完成后都会调用CountDownLatch.countDown(),您的myAlgorithm方法将使用该CountDownLatch.await()方法来等待它们。

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

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

编辑:
只是为了好玩,这里是用一个例子ExecutorServiceCallableFuture

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


 类似资料:
  • 嗨,我正在做一个项目,我已经达到了我非常困的部分。我试图寻找方法来学习如何在繁忙的等待中编写 while 循环,但我没有找到任何东西,我的代码只是作为无限循环运行。有人可以帮助我解释一个繁忙的等待循环应该如何工作,并帮助我打破这个无限循环吗? 该项目希望做到以下几点:早上,学生醒来后(这需要一段随机的时间),他会去洗手间为新的上学日做准备。如果浴室已经客满,学生需要Rest一下(使用yield()

  • 问题内容: 我正在为我的ubuntu服务器(针对我的多客户端匿名聊天程序)实现一种简单的线程池机制,并且需要使我的工作线程进入睡眠状态,直到需要执行一项工作(以函数指针和参数的形式) 。 我当前的系统即将关闭。我(工人线程正在)问经理是否有工作可用,以及是否有5毫秒没有睡眠。如果存在,请将作业添加到工作队列中并运行该函数。糟糕的循环浪费。 什么我 喜欢 做的是做一个简单的事件性的系统。我正在考虑有

  • 问题内容: 问题描述 : - 步骤1: 在主线程中从用户那里获取输入FILE_NAME。 步骤2: 对该文件执行10个操作(即,计数字符,计数行等。),所有这10个操作必须位于单独的线程中。这意味着必须有10个子线程。 步骤3: 主线程等待,直到所有那些子线程完成。 步骤4: 打印结果。 我做了什么 :- 我用3个线程做了一个示例代码。 我不希望您遇到文件操作代码。 问题:- 我上面的代码没有给出

  • 我对Java线程和并发有点陌生。我读过关于同步和锁定块的书。它们让其他线程等待第一个线程完成其工作。 我只想知道一种方式,如果线程a正在执行它的执行,那么线程B不应该等待并跳过共享代码块的执行。

  • 我想做一个小练习来习惯等待/通知。我想做的是简单地启动一个线程,然后用等待让它进入睡眠状态,用通知唤醒它,多次。 我的代码是: 我希望这会是这样 相反,这样做: 所以。。。通知似乎没有唤醒打印机线程? 这不应该是一个死锁,因为通过等待,我释放了所有的锁,所以主服务器不应该有任何对打印机的锁,打印机应该能够唤醒并打印。 我做错了什么?

  • 但这一个也不起作用。正确的答案是加入线程并删除2个睡眠: 我的问题是:为什么我的答案都不能被接受?我的实验室领导问,但他不能给我一个答案。在家里编写了测试代码,它似乎工作得很好。提前感谢您的帮助!