几个Runnable完成后的返回值

Returning value after several Runnable finish

目前我的代码如下:

public String getValue()
{
   StringBuilder builder = new StringBuilder();
   // 1st step
   //some logic to retreive code from database returning value
   //doing something with the returned value add it to collection
   builder.append(someString1);
   // 2nd step
   //some logic to retreive code from database returning value
   //doing something with the returned value add it to collection
   builder.append(someString2);
   // 3rd step
   //some logic to retreive code from database returning value
   //doing something with the returned value add it to collection
   builder.append(someString3);

   return builder.toString();
}

我已经阅读了有关可用于将进程拆分为多个线程的 Runnable 对象的信息,这会将我的代码更改为如下内容:

public String getValue()
{
     Thread firstTread = new Thread(new Process1());
     firstTread.start();
     Thread secondTread = new Thread(new Process1());
     secondTread.start();
     Thread thirdTread = new Thread(new Process1());
     thirdTread.start();

     // here i got confuse how to determine whether all thread allready finished 
     // before returning builder.toString();
}
//this is internal class
class Process1 implements Runnable
{
    public void run()
    {
      //do something and add to StringBuilder
    }
}

class Process2 implements Runnable
{
    public void run()
    {
      //do something and add to StringBuilder
    }
}

class Process3 implements Runnable
{
    public void run()
    {
      //do something and add to StringBuilder
    }
}

如何实现将进程拆分为多个线程的目标?

您使用 Callable,这几乎是一个 Runnable 返回值。而且您使用 ExecutorService 而不是自己创建 Thread 对象。

public String getValue()
{
    ExecutorService threaded = Executors.newFixedThreadPool(NUM_THREADS);
    List<CompletableFuture> results = threaded.invokeAll(
        Arrays.asList(this::process1, this::process2, this::process3);
    results.stream()
        .map(Future::get)  // collects the result from each thread
        .collect(Collectors.joining());
}
private String process1() { return "1"; }
private String process2() { return "2"; }
private String process3() { return "3"; }

编辑: 请注意,输出不会是 "in different order" 因为 invokeAll returns "A list of Futures representing the tasks, in the same sequential order as produced by the iterator for the given task list".

还有其他方法可以并行化您的工作,但要回答有关如何等待线程完成的直接问题,您可以使用

firstTread.join();
secondTread.join();
thirdTread.join();

Callable 更适合这样的任务,因为它是 returns 结果。

ExecutorService 有助于封装线程管理。

  public static void main(String[] args) throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    List<Future<String>> futures = new ArrayList<>();
    futures.add(executorService.submit(new Process1()));
    futures.add(executorService.submit(new Process2()));
    futures.add(executorService.submit(new Process3()));

    StringBuilder sb = new StringBuilder();
    for (Future<String> future : futures) {
      // handle exceptions
      sb.append(future.get());
    }
  }

你要找的不是Runnable,而是一个Callable. Unlike Runnable, a Callable returns a value. This is usually used together with ExecutorService(线程池)。

在线程池中维护线程总是好的,而不是像那样手动生成它们。这可以防止创建不必要且昂贵的线程。这个想法是,不是调用 Thread.start(),而是将 Callable 的实例提交给具有预定义线程数的 ExecutorService 实例。每次提交 return 一个 Future 对象。 Future 对象允许您等待已提交给 ExecutorService 的 Callable 实例的 return 值。

这是您原始代码的修订版:

class Process1 implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "Some string from this callable";
    }
}
// Insert implementation for Process2 and Process2 Callables
   ...

public static void main(String[] args) throws Exception {
   ExecutorService executor = Executors.newFixedThreadPool(3);

   Future<String> process1Future = executor.submit(new Process1());
   Future<String> process2Future = executor.submit(new Process2());
   Future<String> process3Future = executor.submit(new Process3());

   // It will wait here 
   String processedStringByProcess1 = process1Future.get();
   String processedStringByProcess2 = process2Future.get();
   String processedStringByProcess3 = process3Future.get();

   StringBuilder builder = new StringBuilder();
   builder.append(processedStringByProcess1);
   builder.append(processedStringByProcess2);
   builder.append(processedStringByProcess3);

   System.out.println(builder.toString());
}