【问题标题】:How to execute methods which returns different objects using Executors in Java如何使用 Java 中的 Executor 执行返回不同对象的方法
【发布时间】:2023-03-22 22:33:01
【问题描述】:

我有 4 个方法返回不同类的列表。让我们说

public List<A> getA(String param1, String param2){
 //some code here
}
public List<B> getB(String param1, String param2){
 //some code here
}

public List<C> getC(String param1, String param2){
 //some code here
}
public List<D> getD(String param1, String param2){
 //some code here
}

我想同时执行这 4 个方法,我使用 Callable 和 Executor 如下所示

Callable<List<A>> collableA = new Callable<List<A>>() {
        @Override
        public List<A> call() throws Exception {
            return getA();
        }
    };
Callable<List<B>> collableB = new Callable<List<B>>() {
        @Override
        public List<B> call() throws Exception {
            return getB();
        }
    };
Callable<List<D>> collableD = new Callable<List<D>>() {
        @Override
        public List<D> call() throws Exception {
            return getD();
        }
    };
Callable<List<C>> collableC = new Callable<List<C>>() {
        @Override
        public List<C> call() throws Exception {
            return getC();
        }
    };

// add to a list
List<Callable> taskList = new ArrayList<Callable>();
taskList.add(collableA );
taskList.add(collableB);
taskList.add(collableC);
taskList.add(collableD);
//create a pool executor with 4 threads
ExecutorService executor = Executors.newFixedThreadPool(4);

Future<List<FrozenFrameAlert>>  futureFrozen = executor.submit(taskList); 
// getting error here submit() not accepting taskList

我尝试使用InvokeAll()invokeAny() 方法,但没有方法接受这个taskList

【问题讨论】:

  • invokeAll(Collection&lt;? extends Callable&lt;T&gt;&gt; tasks) 应该可以工作。你是如何使用它或你得到什么错误? executor.submit 只接受一个任务。
  • 如果我使用invokeAll() 得到这个错误The method invokeAll(Collection&lt;? extends Callable&lt;T&gt;&gt;) in the type ExecutorService is not applicable for the arguments (List&lt;Callable&gt;) 对于submit() 得到这个错误The method submit(Callable&lt;T&gt;) in the type ExecutorService is not applicable for the arguments (List&lt;Callable&gt;)

标签: java executorservice


【解决方案1】:

我找到了解决方案,您只需要使用通用接口Callable&lt;T&gt; 而不是CallableExecutorService#invokeAll(Collection&lt;? extends Callable&lt;T&gt;&gt; tasks) 方法就可以接受List&lt;Callable&lt;T&gt;&gt;

例子:

List<Callable<List<?>>> taskList = new ArrayList<>();
taskList.add(() -> new ArrayList<>(Arrays.asList(1,2,3)));
taskList.add(() -> new ArrayList<>(Arrays.asList("a","b","c")));
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<List<?>>> futureList = executor.invokeAll(taskList);

for (Future<List<?>> future : futureList) {
    System.out.println(future.get());
}

如果您确实有不同的返回类型,您仍然需要使用 Callable&lt;T&gt; 和一些适当的类型,例如超级接口或至少 Object

【讨论】:

  • 不,它不适合我,我创建了 taskList,正如你所说的那样。 List&lt;Callable&lt;Object&gt;&gt; taskList = new ArrayList&lt;&gt;(); 但在将对象添加到列表时出现以下错误,例如 taskList.add(collableD ); The method add(Callable&lt;Object&gt;) in the type List&lt;Callable&lt;Object&gt;&gt; is not applicable for the arguments (Callable&lt;List&lt;FrozenFrameAlert&gt;&gt;)
  • 它应该仍然适用于List&lt;Callable&lt;Object&gt;&gt;,但我刚刚使用List&lt;Callable&lt;List&lt;?&gt;&gt;&gt; taskList 进行了测试,当所有可调用对象都返回一个通用列表时,这可能会更好。它适用于我的测试用例,Callable 返回List&lt;Integer&gt;,另一个返回List&lt;String&gt;
【解决方案2】:

错误是说你的

List<Callable> taskList = new ArrayList<Callable>();

不是通用的,它应该是 .

List<Callable<List>> taskList = new ArrayList<>();

【讨论】:

    【解决方案3】:

    只需为每个可调用对象使用submit();这将为您提供四个期货,每个期货都有正确的类型:

    Future<List<A>> futureA = executor.submit(callableA);
    Future<List<B>> futureB = executor.submit(callableB);
    etc.
    

    如果您在继续之前需要所有四个期货的结果,您可以依次阻止每个期货:

    List<A> resultA = futureA.get();
    List<B> resultB = futureB.get();
    etc.
    

    要进行更通用的操作,您需要找出一种方法,使所有这些列表都“相同”。但是,如果您不以相同的方式使用它们,那么它们是不同的类型并不重要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-02
      相关资源
      最近更新 更多