• CompletionService


    CompletionService接口:

    将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果。例如,CompletionService 可以用来管理异步 IO ,执行读操作的任务作为程序或系统的一部分提交,然后,当完成读操作时,会在程序的不同部分执行其他操作,执行操作的顺序可能与所请求的顺序不同。

    import java.util.concurrent.Callable;
    import java.util.concurrent.CompletionService;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;

    /**
    * 演示CompletionService的使用
    *
    * @author Administrator
    *
    */

    public class CompletionServiceTest {
    private static final ExecutorService exec = Executors
        .newFixedThreadPool(10);

    public static void main(String[] args) throws InterruptedException,
        ExecutionException {
       CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(
         exec);
       final int nums[] = { 1 };
       for (int i = 0; i < 5; i++) {//提交五个任务
        cs.submit(new Callable<Integer>() {
         public Integer call() throws Exception {
          Thread.sleep(nums[0] * 1000);
          ++nums[0];
          return nums[0];
         }
        });
        // System.out.println(nums[0]);
       }

       for (int i = 0; i < 5; i++) {//得到五个任务
        Future<Integer> f = cs.take();
        System.out.println(f.get());
       }
       exec.shutdown();
    }

    }

    运行程序却发现会有如下结果:

    2
    2
    3
    5
    4

    上边是一次运行结果,也就说不同的任务返回了相同的值。分析原因,是由++nums[0];的非原子性导致的。

    将其加锁,把提交任务的部分改为:

       for (int i = 0; i < 5; i++) {//提交五个任务
        cs.submit(new Callable<Integer>() {
         public Integer call() throws Exception {
          Thread.sleep(nums[0] * 1000);
          synchronized(nums){
           ++nums[0];
          }
          return nums[0];
         }
        });
        // System.out.println(nums[0]);
       }

    运行结果:

    2
    3
    4
    5
    6
    。问题解决

  • 相关阅读:
    K8S学习笔记之k8s使用ceph实现动态持久化存储
    Linux学习笔记之Centos7 自定义systemctl服务脚本
    ELK学习笔记之Kibana权限控制和集群监控
    ELK学习笔记之ELK6.0 X-pack设置用户名和密码
    Linux学习笔记之rsync配置
    K8S学习笔记之Pod的Volume emptyDir和hostPath
    不小心删除了某个包的一部分,重新安装方法
    串口数据解析总结
    CMakeLists 链接库相关指令
    google 开源项目阅读计划
  • 原文地址:https://www.cnblogs.com/macula7/p/1960466.html
Copyright © 2020-2023  润新知