为了账号安全,请及时绑定邮箱和手机立即绑定

“主”线程的 Java 执行器

“主”线程的 Java 执行器

月关宝盒 2023-05-17 17:49:17
我想Executor从程序的&ldquo;主&rdquo;线程(类似于 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@47add263java.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并等待它处理已提交给它的所有内容的好方法?
查看完整描述

4 回答

?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

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

  }

}


查看完整回答
反对 回复 2023-05-17
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

您正在尝试在主线程中执行回调。直接的方法是调用get()

YourResult result = service.submit(task).get();
/* Do something with your result... */

如果您想异步执行回调,您可能会对CompletionStage

CompletableFuture.runAsync(task).thenAccept(r -> /* do something with result */);



查看完整回答
反对 回复 2023-05-17
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

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

executorService.invokeAll();


查看完整回答
反对 回复 2023-05-17
?
缥缈止盈

TA贡献2041条经验 获得超4个赞

您可能正在寻找类似的东西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.


查看完整回答
反对 回复 2023-05-17
  • 4 回答
  • 0 关注
  • 147 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信