Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用ExecutorService并行重复执行许多类似的任务_Java_Multithreading_Concurrency_Executorservice - Fatal编程技术网

Java 使用ExecutorService并行重复执行许多类似的任务

Java 使用ExecutorService并行重复执行许多类似的任务,java,multithreading,concurrency,executorservice,Java,Multithreading,Concurrency,Executorservice,Java代码简化后如下所示: while(someCondition) { SomeType a = CalcResult(param1); SomeType b = CalcResult(param2); SomeType c = CalcResult(param3); // Do something with a, b and c } CalcResult()非常耗时。该应用程序在SMP系统上运行。有一个推动尝试同时运行所有三个计算,每个都在自己的CPU上

Java代码简化后如下所示:

while(someCondition)
{
    SomeType a = CalcResult(param1);
    SomeType b = CalcResult(param2);
    SomeType c = CalcResult(param3);

    // Do something with a, b and c
}
CalcResult()
非常耗时。该应用程序在SMP系统上运行。有一个推动尝试同时运行所有三个计算,每个都在自己的CPU上,而不是按顺序运行它们。需要并行的总是这3个任务,而不是任意数量的任务(这就是算法)。每项任务可能比其他任务花费的时间稍多或稍少,但通常差异不大(20-30%)

由于他们需要返回结果,我查看了Executor服务解决方案,例如:

ExecutorService executor=Executors.newSingleThreadExecutor();
Callable Callable=new Callable(){
@凌驾
公共整数调用(){
返回2;
}
};
未来=执行人提交(可调用);
//get()返回2
executor.shutdown();
由于我对Java的经验主要是在servlet/JSP开发中,所以我没有线程方面的经验,也不确定该代码段是否可以处理3个任务而不是一个任务


我如何提交3个任务,每个任务都有自己的参数值,并等待所有任务返回计算结果,同时确保为它们创建线程不会否定在它们自己的CPU上运行的优势,即有没有办法在
while()之前创建一次线程
循环开始,然后只需将一个新的
参数推入循环中的每个线程,唤醒它们,并等待它们执行所有计算?

执行器。newSingleThreadExecutor()
将只创建一个线程。您需要的是执行器。newFixedThreadPool(3)
。在while循环之前调用它,这样线程只创建一次

创建可调用包装器:

class MyCallable implements Callable<V> {
    P p;
    MyCallable(P parameter) {
        p = parameter;
    }
    V call() {
        return CalcResult(p);
    }
}
类MyCallable实现可调用{
P;
MyCallable(P参数){
p=参数;
}
V call(){
返回计算结果(p);
}
}
while循环:

ExecutorService executor = Executors.newFixedThreadPool(3);
while (cond) {
    Future<V> aFuture = executor.submit(new MyCallable(param1));
    Future<V> bFuture = executor.submit(new MyCallable(param2));
    Future<V> cFuture = executor.submit(new MyCallable(param3));

    // this will block until all calculations are finished:
    a = aFuture.get();
    b = bFuture.get();
    c = cFuture.get();

   // do something with a/b/c, e.g. calc new params.
}
ExecutorService executor=Executors.newFixedThreadPool(3);
while(cond){
futureafuture=executor.submit(新的MyCallable(参数1));
Future bFuture=executor.submit(新的MyCallable(参数2));
Future cFuture=executor.submit(新的MyCallable(参数3));
//这将阻止,直到所有计算完成:
a=aFuture.get();
b=bFuture.get();
c=cFuture.get();
//对a/b/c执行某些操作,例如计算新参数。
}

您可以为应用程序创建executor服务,专门用于处理这些计算。池大小可能会有所不同,具体取决于您是否打算同时运行多个计算:

ExecutorService service = Executors.newFixedThreadPool(3);

Future<Integer> submitA = service.submit(new Callable<Integer>() {
  @Override
  public Integer call() throws Exception {
    return processA();
  }
});
Future<Integer> submitB = service.submit(new Callable<Integer>() {
  @Override
  public Integer call() throws Exception {
    return processB();
  }
});
Future<Integer> submitC = service.submit(new Callable<Integer>() {
  @Override
  public Integer call() throws Exception {
    return processC();
  }
});

int result = submitA.get() + submitB.get() + submitC.get();
ExecutorService=Executors.newFixedThreadPool(3);
Future submitA=service.submit(new Callable()){
@凌驾
公共整数调用()引发异常{
返回processA();
}
});
Future submitB=service.submit(new Callable()){
@凌驾
公共整数调用()引发异常{
返回进程b();
}
});
Future submitC=service.submit(new Callable()){
@凌驾
公共整数调用()引发异常{
返回进程c();
}
});
int result=submitA.get()+submitB.get()+submitC.get();
在这种情况下,您需要确保在每次运行计算时都没有创建线程池,在这种情况下,创建线程池的影响与保存相比将很小-假设通过拆分任务可以减少运行时间

我没有Java线程的经验


那你是在玩火。并发是很棘手的,因为有一些故障模式是顺序编程不可能实现的,但是运行时并不能避免您自己的错误。所以,在粘贴So中的代码之前,您应该至少阅读第1-6章,以了解发生了什么

将执行器留在周围(或使用例如ForkJoinPool.commonPool()),这样您就不必每次都花钱启动和停止它。注意:SingleThreadExecutor只有一个线程。所以你会想用另一个。我支持Jeffrey关于ForkJoinPool的建议。正如我所说,我对Java线程没有任何经验,所以仍然不清楚如何使用你的建议。实际上,你已经差不多做到了。在将来调用
get
将被阻止,直到结果就绪。因此,如果您提交这三个任务并确保未来安全,然后依次调用这三个任务的get方法,那么可以确保在最后一个任务返回时这三个任务都已完成。如果最后一个在第二个之前完成,那么它将立即返回结果。对于并行性,不要使用SingleThreadExecutor,例如答案中推荐的固定线程执行器。明白了,谢谢!正如Adrian在回答中提到的,我正在努力实现具体的实现。对不起,我仍然不清楚如何调用并等待完成,您愿意将这些部分添加到回答中吗?谢谢@看到第二段了吗。。。每次调用
get
都将阻塞,直到相应的future完成其任务。因此,当
cFuture.get()
返回时,所有三个任务都已完成。是的,看到了eidt-谢谢!我的问题是,
CalcResult
是一个库函数,它返回一个值。它是否需要
返回CalcResult(p)
?@ajeh,对不起,执行者必须声明为ExecutorService@ajeh将
class MyCallable
更改为
class MyCallable
,并将类定义移动到单独的文件中。
ExecutorService service = Executors.newFixedThreadPool(3);

Future<Integer> submitA = service.submit(new Callable<Integer>() {
  @Override
  public Integer call() throws Exception {
    return processA();
  }
});
Future<Integer> submitB = service.submit(new Callable<Integer>() {
  @Override
  public Integer call() throws Exception {
    return processB();
  }
});
Future<Integer> submitC = service.submit(new Callable<Integer>() {
  @Override
  public Integer call() throws Exception {
    return processC();
  }
});

int result = submitA.get() + submitB.get() + submitC.get();