“主”线程的 Java 执行器

我想Executor从程序的“主”线程(类似于 Android 中的主循环程序)创建一个,然后运行直到它处理完提交给它的所有内容:

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)

    

我可以在一个新线程上开始一个ExecutorService线程,然后等待它,但这似乎很浪费。


有没有一种从当前线程创建一个Executor并等待它处理已提交给它的所有内容的好方法?


月关宝盒
浏览 150回答 4
4回答

犯罪嫌疑人X

使用 Guava 的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);  }}

幕布斯6054654

您正在尝试在主线程中执行回调。直接的方法是调用get():YourResult result = service.submit(task).get(); /* Do something with your result... */如果您想异步执行回调,您可能会对CompletionStageCompletableFuture.runAsync(task).thenAccept(r -> /* do something with result */);

MMMHUHU

此处invokeAll()记录的方法 等待所有任务完成 您可以这样做executorService.invokeAll();

缥缈止盈

您可能正在寻找类似的东西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 ...}这将在项目完成后立即对其进行处理。如果你能等到你拥有一切,然后一次性处理它,你可以使用番石榴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.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java