Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.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 什么时候我应该使用CompletionService而不是ExecutorService?_Java_Multithreading_Concurrency_Completion Service - Fatal编程技术网

Java 什么时候我应该使用CompletionService而不是ExecutorService?

Java 什么时候我应该使用CompletionService而不是ExecutorService?,java,multithreading,concurrency,completion-service,Java,Multithreading,Concurrency,Completion Service,我刚在中找到CompletionService。然而,这并没有真正展示CompletionService相对于标准ExecutorService的优势。同样的代码可以用任何一种语言编写。那么,CompletionService什么时候有用 你能给出一个简短的代码示例,让它清晰明了吗?例如,此代码示例仅显示不需要CompletionService的位置(=相当于ExecutorService) ExecutorService taskExecutor=Executors.newCachedThre

我刚在中找到CompletionService。然而,这并没有真正展示CompletionService相对于标准ExecutorService的优势。同样的代码可以用任何一种语言编写。那么,CompletionService什么时候有用

你能给出一个简短的代码示例,让它清晰明了吗?例如,此代码示例仅显示不需要CompletionService的位置(=相当于ExecutorService)

ExecutorService taskExecutor=Executors.newCachedThreadPool();
//CompletionService任务CompletionService=
//新的ExecutorCompletionService(taskExecutor);
Callable Callable=new Callable(){
@凌驾
public Long call()引发异常{
返回1L;
}
};
Future=//taskCompletionService.submit(可调用);
任务执行者提交(可调用);
而(!future.isDone()){
//做一些工作。。。
System.out.println(“正在做某事…”);
}
试一试{
System.out.println(future.get());
}捕捉(中断异常e){
e、 printStackTrace();
}捕获(执行例外){
e、 printStackTrace();
}

我认为javadoc最好地回答了以下问题:
CompletionService
在某种程度上是有用的,而
ExecutorService
则不是

将新异步任务的生成与已完成任务的结果的使用分离的服务

基本上,此接口允许程序拥有创建和提交任务(甚至检查这些提交的结果)的生产者,而不知道这些任务结果的任何其他使用者。同时,知道
CompletionService
的消费者可以
poll
获取结果,而无需知道生产者提交了任务


作为记录,我可能是错的,因为时间太晚了,但我相当肯定,该博客文章中的示例代码会导致内存泄漏。如果没有一个活跃的消费者将结果从
ExecutorCompletionService
的内部队列中取出,我不确定博主希望该队列如何耗尽。

基本上,如果您希望并行执行多个任务,然后按照完成顺序处理它们,您可以使用
CompletionService
。因此,如果我执行5个作业,
CompletionService
将为我提供第一个完成的作业。示例中,只有一个任务,除了提交
可调用的
的能力之外,对
执行者没有额外的价值,忽略了许多细节:

  • ExecutorService=传入队列+工作线程
  • CompletionService=传入队列+工作线程+输出队列

使用
ExecutorService
,一旦您提交了要运行的任务,您需要手动编写代码,以便高效地获得任务完成的结果

使用
CompletionService
,这几乎是自动化的。由于您只提交了一个任务,所以您所提交的代码中的差异不是很明显。但是,假设您有一个要提交的任务列表。在下面的示例中,多个任务提交给CompletionService。然后,它不再试图找出哪个任务已经完成(以获取结果),而是要求CompletionService实例在结果可用时返回结果

public class CompletionServiceTest {

        class CalcResult {
             long result ;

             CalcResult(long l) {
                 result = l;
             }
        }

        class CallableTask implements Callable<CalcResult> {
            String taskName ;
            long  input1 ;
            int input2 ;

            CallableTask(String name , long v1 , int v2 ) {
                taskName = name;
                input1 = v1;
                input2 = v2 ;
            }

            public CalcResult call() throws Exception {
                System.out.println(" Task " + taskName + " Started -----");
                for(int i=0;i<input2 ;i++) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        System.out.println(" Task " + taskName + " Interrupted !! ");
                        e.printStackTrace();
                    }
                    input1 += i;
                }
                System.out.println(" Task " + taskName + " Completed @@@@@@");
                return new CalcResult(input1) ;
            }

        }

        public void test(){
            ExecutorService taskExecutor = Executors.newFixedThreadPool(3);
            CompletionService<CalcResult> taskCompletionService = new ExecutorCompletionService<CalcResult>(taskExecutor);

            int submittedTasks = 5;
            for (int i=0;i< submittedTasks;i++) {
                taskCompletionService.submit(new CallableTask (
                        String.valueOf(i), 
                            (i * 10), 
                            ((i * 10) + 10  )
                        ));
               System.out.println("Task " + String.valueOf(i) + "subitted");
            }
            for (int tasksHandled=0;tasksHandled<submittedTasks;tasksHandled++) {
                try {
                    System.out.println("trying to take from Completion service");
                    Future<CalcResult> result = taskCompletionService.take();
                    System.out.println("result for a task availble in queue.Trying to get()");
                    // above call blocks till atleast one task is completed and results availble for it
                    // but we dont have to worry which one

                    // process the result here by doing result.get()
                    CalcResult l = result.get();
                    System.out.println("Task " + String.valueOf(tasksHandled) + "Completed - results obtained : " + String.valueOf(l.result));

                } catch (InterruptedException e) {
                    // Something went wrong with a task submitted
                    System.out.println("Error Interrupted exception");
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    // Something went wrong with the result
                    e.printStackTrace();
                    System.out.println("Error get() threw exception");
                }
            }
        }
    }
公共类CompletionServiceTest{
类CalcResult{
长期结果;
CalcResult(长l){
结果=l;
}
}
类CallableTask实现可调用{
字符串taskName;
长输入1;
int输入2;
CallableTask(字符串名,长v1,int v2){
taskName=名称;
输入1=v1;
输入2=v2;
}
public CalcResult调用()引发异常{
System.out.println(“任务”+taskName+“已启动------”);

对于(inti=0;i首先,如果我们不想浪费处理器时间,我们将不使用

while (!future.isDone()) {
        // Do some work...
}
我们必须使用

service.shutdown();
service.awaitTermination(14, TimeUnit.DAYS);
这段代码的缺点是它将关闭
ExecutorService
。如果我们想继续使用它(即,我们有一些递归任务创建),我们有两种选择:invokeAll或
ExecutorService

invokeAll
将等待所有任务完成。
ExecutorService
使我们能够逐个获取或轮询结果

最后是递归示例:

ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUMBER);
ExecutorCompletionService<String> completionService = new ExecutorCompletionService<String>(executorService);

while (Tasks.size() > 0) {
    for (final Task task : Tasks) {
        completionService.submit(new Callable<String>() {   
            @Override
            public String call() throws Exception {
                return DoTask(task);
            }
        });
    } 

    try {                   
        int taskNum = Tasks.size();
        Tasks.clear();
        for (int i = 0; i < taskNum; ++i) {
            Result result = completionService.take().get();
            if (result != null)
                Tasks.add(result.toTask());
        }           
    } catch (InterruptedException e) {
    //  error :(
    } catch (ExecutionException e) {
    //  error :(
    }
}
ExecutorService ExecutorService=Executors.newFixedThreadPool(线程编号);
ExecutorCompletionService completionService=新的ExecutorCompletionService(executorService);
while(Tasks.size()>0){
对于(最终任务:任务){
completionService.submit(新的可调用(){
@凌驾
公共字符串调用()引发异常{
返回DoTask(任务);
}
});
} 
试试{
int taskNum=Tasks.size();
任务。清除();
对于(int i=0;i
在运行时自己查看,尝试实现这两种解决方案(Executorservice和Completionservice),您将看到它们的行为有多不同,何时使用其中一种会更清楚。
这里有一个例子,如果您想要

假设您有5个长期运行的任务(可调用任务),并且您已经将这些任务提交给executer服务。现在想象一下,您不想等待所有5个任务竞争,而是想
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUMBER);
ExecutorCompletionService<String> completionService = new ExecutorCompletionService<String>(executorService);

while (Tasks.size() > 0) {
    for (final Task task : Tasks) {
        completionService.submit(new Callable<String>() {   
            @Override
            public String call() throws Exception {
                return DoTask(task);
            }
        });
    } 

    try {                   
        int taskNum = Tasks.size();
        Tasks.clear();
        for (int i = 0; i < taskNum; ++i) {
            Result result = completionService.take().get();
            if (result != null)
                Tasks.add(result.toTask());
        }           
    } catch (InterruptedException e) {
    //  error :(
    } catch (ExecutionException e) {
    //  error :(
    }
}
  private Object waitingGet(boolean interruptible) {
        Signaller q = null;
        boolean queued = false;
        int spins = -1;
        Object r;
        while ((r = result) == null) {
            if (spins < 0)
                spins = (Runtime.getRuntime().availableProcessors() > 1) ?
                    1 << 8 : 0; // Use brief spin-wait on multiprocessors
            else if (spins > 0) {
                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
                    --spins;
            }
    private class QueueingFuture extends FutureTask<Void> {
    QueueingFuture(RunnableFuture<V> task) {
        super(task, null);
        this.task = task;
    }
    protected void done() { completionQueue.add(task); }
    private final Future<V> task;
}
package com.barcap.test.test00;

import java.util.concurrent.*;

/**
 * Created by Sony on 25-04-2019.
 */
public class ExecutorCompletest00 {

    public static void main(String[] args) {

        ExecutorService exc= Executors.newFixedThreadPool( 10 );
        ExecutorCompletionService executorCompletionService= new ExecutorCompletionService( exc );

        for (int i=1;i<10;i++){
            Task00 task00= new Task00( i );
            executorCompletionService.submit( task00 );
        }
        for (int i=1;i<20;i++){
            try {
                Future<Integer> future= (Future <Integer>) executorCompletionService.take();
                Integer inttest=future.get();
                System.out.println(" the result of completion service is "+inttest);

               break;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}
package com.barcap.test.test00;

import java.util.*;
import java.util.concurrent.*;

/**
 * Created by Sony on 25-04-2019.
 */
public class ExecutorServ00 {

    public static void main(String[] args) {
        ExecutorService executorService=Executors.newFixedThreadPool( 9 );
        List<Future> futList= new ArrayList <>(  );
        for (int i=1;i<10;i++) {
           Future result= executorService.submit( new Task00( i ) );
           futList.add( result );
        }

         for (Future<Integer> futureEach :futList ){
             try {
              Integer inm=   futureEach.get();

                 System.out.println("the result of future executorservice is "+inm);
                 break;
             } catch (InterruptedException e) {
                 e.printStackTrace();
             } catch (ExecutionException e) {
                 e.printStackTrace();
             }
         }
    }
}
package com.barcap.test.test00;

import java.util.concurrent.*;

/**
 * Created by Sony on 25-04-2019.
 */
public class Task00 implements Callable<Integer> {

    int i;

    public Task00(int i) {
        this.i = i;
    }

    @Override
    public Integer call() throws Exception {
        System.out.println(" the current thread is "+Thread.currentThread().getName()  +" the result should be "+i);
        int sleepforsec=100000/i;
         Thread.sleep( sleepforsec );
        System.out.println(" the task complted for "+Thread.currentThread().getName()  +" the result should be "+i);



        return i;
    }
}