[英]Java Executor for “main” thread
我想从程序的“主”线程(类似于Android中的主循环程序)创建一个Executor
,然后运行直到它处理了提交给它的所有内容:
public class MyApp {
private static Callable<Integer> task = () -> {
// ... return an int somehow ...
};
public static void main(String[] args) throws ExecutionException, InterruptedException {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
Thread main = Thread.currentThread();
ExecutorService executorService = Executors.newSingleThreadExecutor(r -> main);
service.submit(task).addListener(() -> {
/// ... do something with the result ...
}, executorService);
executorService.awaitTermination(100, TimeUnit.SECONDS);
}
}
但是我得到了一个IllegalThreadState
异常:
SEVERE: RuntimeException while executing runnable MyApp$$Lambda$20/0x00000008000a6440@71f06a3c with executor java.util.concurrent.Executors$FinalizableDelegatedExecutorService@47add263
java.lang.IllegalThreadStateException
at java.base/java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:926)
at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1343)
at java.base/java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:687)
at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1137)
at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:957)
at com.google.common.util.concurrent.AbstractFuture.set(AbstractFuture.java:726)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.afterRanInterruptibly(TrustedListenableFutureTask.java:131)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:133)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
我可以在新线程上启动ExecutorService
,然后等待它,但这似乎很浪费。
有没有什么好方法可以从当前线程创建Executor
,并等待它处理已提交给它的所有内容?
您可能正在寻找类似CompletionService
东西:您向此任务提交任务,并且它按完成顺序将其返回。
ExecutorService service = Executors.newFixedThreadPool(1);
ExecutorCompletionService<Integer> comp = new ExecutorCompletionService<>(service);
comp.submit(task);
// ... I assume you want to submit N tasks.
for (int i = 0; i < N; ++i) {
Future<Integer> future = comp.take();
Integer result = future.get();
// ... do something with the result ...
}
项目完成后,将立即对其进行处理。 如果您能够等到拥有所有东西之后再进行一次处理,则可以使用Guava的Futures.allAsList
:
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
List<Callable<Integer>> tasks = ...;
List<ListenableFuture<Integer>> futures = new ArrayList<>();
for (Callable<Integer> task : tasks) {
futures.add(service.submit(task));
}
ListenableFuture<List<Integer>> resultsFuture = Futures.allAsList(futures);
List<Integer> results = resultsFuture.get();
// Process the results.
MoreExecutors.newDirectExecutorService()
这将确保提交的代码将在ThreadPool的同一线程中执行。 我知道,它不是主线程,但至少您不会像想要的那样仅为侦听器创建其他新线程。
import com.google.common.util.concurrent.*;
import org.junit.jupiter.api.Test;
import java.util.concurrent.*;
class ExecutorTest {
private static Callable<Integer> task = () -> {
System.out.println("in call: " + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(1);
return 0;
};
@Test
void test() throws InterruptedException {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
ExecutorService executor = MoreExecutors.newDirectExecutorService();
service.submit(task).addListener(() -> {
System.out.println("in listener: " + Thread.currentThread().getName());
}, executor);
executor.awaitTermination(2, TimeUnit.SECONDS);
}
}
您正在尝试在主线程中执行回调。 直接的方法是调用get()
:
YourResult result = service.submit(task).get();
/* Do something with your result... */
如果要异步执行回调,则可能对CompletionStage
感兴趣
CompletableFuture.runAsync(task).thenAccept(r -> /* do something with result */);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.