[英]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
西装更适合此类任务,因为它返回结果。
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 。 与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());
}
您使用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
返回“代表任务的期货列表,其顺序与给定任务列表的迭代器产生的顺序相同” 。
还有其他方法可以并行处理您的工作,但是要回答有关如何等待线程完成的直接问题,可以使用
firstTread.join();
secondTread.join();
thirdTread.join();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.