我正在尝试对按顺序方式接收的元素执行昂贵且可变长度的任务。必须保持元素顺序,同时仍然快速处理每个元素。
下面是SSCWE( W 错误!),是我尝试并行化处理。有没有办法确保每次调用processSomething()
都在自己的线程中执行,同时在查看ExecutorCompletionService
时仍保持FIFO?
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadingHelper {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(20);
ExecutorCompletionService<String> compService
= new ExecutorCompletionService<String>(pool);
// process some data
processSomething(compService, "1.");
processSomething(compService, "2..");
processSomething(compService, "3...");
processSomething(compService, "4....");
processSomething(compService, "5.....");
// print out the processed data
try {
System.out.println(compService.take().get());
System.out.println(compService.take().get());
System.out.println(compService.take().get());
System.out.println(compService.take().get());
System.out.println(compService.take().get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public static synchronized void processSomething(
CompletionService<String> compService, final String x) {
Callable<String> c = new Callable<String>() {
@Override
public String call() throws Exception {
// this represents the variable and expensive
// amount of time it takes to process x
long rand = (long) (Math.random() * 100);
Thread.sleep(rand);
// this represents the processing of x
String xProcessed = x.replace(".", "!");
return xProcessed;
}
};
compService.submit(c);
}
}
典型输出
4!!!!
2!!
1!
5!!!!!
3!!!
但我想要
1!
2!!
3!!!
4!!!!
5!!!!!
答案 0 :(得分:2)
使用期货代替 CompletionService 以特定顺序获取结果,并仍然可以从并行执行中受益:
ExecutorService pool = Executors.newFixedThreadPool(20);
List<Future<String>> futures = new ArrayList<>();
futures.add(pool.submit(makeCallable("1.")));
// ...
for (Future<String> future : futures) {
try {
System.out.println(future.get());
} catch (...) {
...
}
}
public static Callable<String> makeCallable(String x) {
Callable<String> c = ...;
return c;
}