【问题标题】:Getting results back to the caller from worker threads从工作线程将结果返回给调用者
【发布时间】:2019-09-07 22:52:57
【问题描述】:

有一些关于 SO 的答案,但我正在寻找使用我的代码的解决方案以便清晰理解。

我使用 Executor 创建了工作线程,工作完成后,工作线程将结果返回给调用者(main)

工人

public class Worker implements Runnable {

    private final int num;

    public Worker(int num) {
        this.num = num;
    }

    @Override
    public void run() {
        System.out.println("Starting job: " + num);
        try {
            Thread.sleep(2000);
            System.out.println("end job:" + num);

            String result = "result " + num; // how to pass all the results back to the caller

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

工人测试

public class WorkerTest {

    private static List<String> result = new ArrayList<>();

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Runnable worker = new Worker(i);
            executorService.execute(worker);
        }
        executorService.shutdown();
        while(!executorService.isTerminated());
    }
}

【问题讨论】:

标签: java multithreading


【解决方案1】:

您应该实现Callable,而不是实现Runnable,然后使用返回Future的方法

public class Worker implements Callable<String> {
  @Override
  public String call() {
    return "123";
  }
}


ExecutorService es = Executors.newFixedThreadPool(5);
Future<?> f = es.submit(new Worker());
String result = f.get(); // 123

【讨论】:

  • 您能否使用我的代码示例提供答案,我无法理解它
  • 谢谢,我很感激,我明白了,你能不能把它修改为有 10 个提交,并等待所有 10 个完成,这样整个画面就会很明显。
【解决方案2】:

> 我无法理解 [Futures]。

也许稍微看一眼幕后会有帮助

Future是一个接口,但是有一些标准库类,我们不知道它的名字,那就是implements Future。我们假设它叫FutureImpl

FutureImpl 实例有一个由Future API 指定的get() 方法,它还有另一个我们看不到的方法,但我们称之为put(x)

当 Karol Dowbecki 的示例代码向执行器服务提交任务时,执行器服务会创建一个新的 FutureImpl 实例并用它做两件事:

  1. 它提供了对将要执行您的任务的工作线程的引用,并且,
  2. 它返回来自es.submit(...) 调用的引用。

    Future<?> f = es.submit(...);
    

工作线程会调用你给它的任务函数,然后它会获取返回的值,并把它存储在FutureImpl对象中:

futureImpl.put(task.Call());

注意! ffutureImpl 是同一对象的两个不同名称。唯一不同的是,工作线程知道它是FutureImpl类的实例,而主线程只知道它是implements Future的某个类的实例。

不管怎样,回到主线程......它可以在worker做它的时候做其他事情,然后最终,主线程可以尝试检索值:

String result = f.get();

如果任务已经完成,并且worker在主线程调用f.get()之前已经调用了futureImpl.put(...),那么f.get()将立即返回该值。但是,如果主线程首先调用f.get(),那么get() 调用将等待,直到工作线程完成任务并存储值。

【讨论】:

    【解决方案3】:

    这是您的完整代码 公共类 WorkerTest { 私有静态列表结果 = new ArrayList();

    public static void main(String[] args) throws Exception {
        Future[] futures = new Future[10];
        ExecutorService ex = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Callable worker = new Worker(i);
    
            futures[i] = ex.submit(worker);
    
        }
        for (int i = 0; i < 10; i++) {
            String resultString = (String) futures[i].get();
            System.out.println(resultString);
        }
        ex.shutdown();
        while (!ex.isTerminated());
    }
    
    }
    
    class Worker implements Callable<String> {
    
    private final int num;
    
    public Worker(int num) {
        super();
        this.num = num;
    }
    
    @Override
    public String call() throws Exception {
        String result = null;
        System.out.println("starting job " + num);
        try {
            Thread.sleep(2000);
            System.out.println("end job " + num);
            result = "result" + num;
    
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    

    }

    如果您想将结果存储在列表中,也可以这样做。

    public class ExecutorTest {
    private static List<String> result = new ArrayList<>();
    
    public static void main(String[] args) throws Exception {
        ExecutorService ex = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Callable worker = new Worker(i);
    
            Future<String> stringResult= ex.submit(worker);
            String output = stringResult.get();
            result.add(output);
            System.out.println(output);
    
        }
        ex.shutdown();
        while (!ex.isTerminated());
        System.out.println("All results received frmo executor service ");
        System.out.println(result);
    }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 2015-07-10
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2015-05-09
      相关资源
      最近更新 更多