几次Runnable完成后返回值

时间:2017-11-13 08:03:43

标签: java multithreading 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
    }
}

我已经读过可用于将进程拆分为多个线程的Runnable对象,这会将我的代码改为:

File file = new File("Text.txt");
Scanner scan = new Scanner(file);
while(scan.hasNextLine()){
String str = scan.nextLine();
pw.println(str);
}

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

4 个答案:

答案 0 :(得分:3)

Callable更适合此类任务,因为它返回结果。

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());
    }
  }

答案 1 :(得分:3)

您要找的不是Runnable,而是Callable。与Runnable不同,Callable返回一个值。这通常与ExecutorService(线程池)一起使用。

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

以下是原始代码的修订版:

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());
}

答案 2 :(得分:2)

您使用的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"; }

编辑: 请注意,输出不会“按不同顺序”,因为invokeAll returns "A list of Futures representing the tasks, in the same sequential order as produced by the iterator for the given task list"

答案 3 :(得分:0)

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

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