此时情绪此时天,无事小神仙
好好生活,平平淡淡每一天

编辑

多线程Callable处理数据

1.数据拆分多线程Callable处理

1.定义一个等于CPU核心数的线程池
2.根据数据 List 处理每个线程可以分到的数量List
3.Callable 线程处理数据
4.Future 获取Callcable线程处理后的数据
5.把 Future 获取的数据重新 addAll 进 List
6.返回数据

代码如下:

public List<String> packageStrings(List<String> list) throws InterruptedException, ExecutionException{
        // 开始时间
        long start = System.currentTimeMillis();
        // 线程数量=CPU核心数
        int threadNum = Runtime.getRuntime().availableProcessors();
        // 每条线程处理的数据
        int count = list.size() / threadNum;
        if (0 != list.size() % count) {
            threadNum++;
        }
        // 创建一个大小等于CPU核心数的线程池
        ExecutorService exec = Executors.newFixedThreadPool(threadNum);
        try {
            // 定义一个任务集合
            List<Callable<List<String>>> tasks = new ArrayList<Callable<List<String>>>();
            int end = 0;
            for (int i = 0; i < threadNum; i++) {
                if (i * count + count > list.size()) {
                    end = list.size();
                } else {
                    end = i * count + count;
                }
                // 确定每条线程的数据
                List<String> cutList = list.subList(i * count, end);
                final List<String> listStr = cutList;
                final List<String> newList = new ArrayList<String>();
                Callable<List<String>> task = new Callable<List<String>>() {
                    @Override
                    public List<String> call() throws Exception {
                        for (String str : listStr) {
                            // 封装处理数据
                            str = packageString(str);
                            newList.add(str);
                        }
                        return newList;
                    }
                };
                // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
                tasks.add(task);
            }
            // 获取数据并重新set
            List<Future<List<String>>> results = exec.invokeAll(tasks);
            list.clear();
            for (Future<List<String>> future : results) {
                list.addAll(future.get());
            } 
        } finally {
            // 关闭线程池
            exec.shutdown();
            // if all tasks have completed following shut down
            while(!exec.isTerminated());
        }
        //System.out.println(list.toString());
        System.err.println("\n执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
        return list;
    } 

 2.数据未拆分多线程Callable处理数据

1.定义一个等于CPU核心数的线程池池

2.定义 Callable 的任务集合

3.遍历List处理数据

4.把 Callable 添加到 Callable 的任务集合中

5.把通过 Future 获取的数据并重新 add 进 List

6.返回数据

代码如下:

  public List<String> CallablePackageStrings(List<String> list) throws InterruptedException, ExecutionException{
        // 开始时间
        long start = System.currentTimeMillis();
        // 创建一个大小等于CPU核心数的线程池
        ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        // 定义一个任务集合
        try {
            List<Callable<String>> tasks = new ArrayList<Callable<String>>();
            for (final String str : list) {
                Callable<String> task = new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        // 封装处理数据
                        return packageString(str);
                    }
                };
                // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
                tasks.add(task);
            }
            List<Future<String>> results = exec.invokeAll(tasks);
            list.clear();
            for (Future<String> future : results) {
                list.add(future.get());
            } 
        } finally {
            // 关闭线程池
            exec.shutdown();
            // if all tasks have completed following shut down
            while(!exec.isTerminated());
        }
        //System.out.println(list.toString());
        System.err.println("\n执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
        return list;
    } 

 

 3.数据未拆分多线程Callable处理数据精简代码

1.定义一个等于CPU核心数的线程池

2.定义Future的任务集合

3.遍历List处理数据

4.把 Future 添加到 Future 的任务集合中

5.把通过 Future 获取的数据并重新 add 进 List

6.返回数据

代码如下:

 public List<String> packageStrings(List<String> list) throws InterruptedException, ExecutionException{
        // 开始时间
        long start = System.currentTimeMillis();
        // 创建一个大小等于CPU核心数的线程池
        ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        // 定义FutureTask任务集合
        try {
            List<Future<String>> futures = new ArrayList<Future<String>>();
            for (final String str : list) {
                Future<String> future = exec.submit(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        // 封装处理数据
                        return packageString(str);
                    }
                });
                futures.add(future);
            }
            list.clear();
            for (Future<String> future : futures) {
                list.add(future.get());
            } 
        } finally {
            // 关闭线程池
            exec.shutdown();
            // if all tasks have completed following shut down
            while(!exec.isTerminated());
        }
        //System.out.println(list.toString());
        System.err.println("\n执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
        return list;
   }

以上三种推荐第三种:

第二种是在第一种基础上进行优化

第三种是在第二种基础上进行冗余代码去除

posted @ 2020-04-28 12:15  踏步  阅读(761)  评论(0编辑  收藏  举报