zoukankan      html  css  js  c++  java
  • [并发编程]并发编程第二篇:利用并发编程,实现计算大量数据的和

    利用并发编程,实现计算大量数据的和

    实现代码:

    package tj.pojo.generate.main;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.FutureTask;
    
    public class ConcurrentCalculator {
    
        private ExecutorService exec;
        private int cpuCoreNumber;
        private List<Future<Long>> tasks = new ArrayList<Future<Long>>();
    
        // 内部类
        class SumCalculator implements Callable<Long> {
            private int[] numbers;
            private int start;
            private int end;
    
            public SumCalculator(final int[] numbers, int start, int end) {
                this.numbers = numbers;
                this.start = start;
                this.end = end;
            }
            @Override
            public Long call() throws Exception {
                Long sum = 0L;
                for (int i = start; i < end; i++) {
                    sum += numbers[i];
                }
                System.out.println(String.format("%s~%s的和为%s", start, end, sum));
                return sum;
            }
    
        }
    
        public ConcurrentCalculator() {
            cpuCoreNumber = Runtime.getRuntime().availableProcessors();
            System.out.println("CPU核心数:" + cpuCoreNumber);
            exec = Executors.newFixedThreadPool(cpuCoreNumber);
    
        }
    
        public Long sum(final int[] numbers) {
            for (int i = 0; i < cpuCoreNumber; i++) {
                int increment = numbers.length / cpuCoreNumber + 1;
                int start = increment * i;
                int end = start + increment;
                if (end > numbers.length) {
                    end = numbers.length;
                }
                SumCalculator task = new SumCalculator(numbers, start, end);
    
                FutureTask<Long> future = new FutureTask<Long>(task);
                tasks.add(future);
                System.out.println("添加一个任务,总任务数为:" + tasks.size());
                if (!exec.isShutdown()) {
                    exec.submit(future);
                    // ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。
                    // exec.submit(task);
                }
            }
            System.out.println("任务分配完成,总任务数为:" + tasks.size());
            return getResult();
        }
    
        public Long getResult() {
            Long sums = 0L;
            for (Future<Long> task : tasks) {
                try {
                    Long sum = task.get();
                    sums += sum;
                    System.out.println("当前总合计:" + sums);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
            return sums;
        }
    
        public void close() {
            exec.shutdown();
        }
    }

    其中,在代码的第62行~第64行,由于不了解ExecutoreService.submit(Runnable task)方法的功能。

    同时FutureTask<Long> future和SumCalculator task都实现了Runnable接口,造成代码调用时,进程一直不结束。

    传递了FutureTask<Long> future才正确执行。

                    exec.submit(future);
                    // ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。
                    // exec.submit(task);

    测试方法:

    public static void test() {
            int[] numbers = new int[100];
            for (int i = 0; i < 100; i++) {
                numbers[i] = i + 1;
            }
            tj.pojo.generate.main.ConcurrentCalculator cc = new tj.pojo.generate.main.ConcurrentCalculator();
            Long sum = cc.sum(numbers);
            System.out.println("1~100的和为" + sum);
            cc.close();
        }

    FutureTask的实现代码:

    public class FutureTask<V> implements RunnableFuture<V>

    FutureTask类实现了RunnableFuture接口,RunnableFuture接口的实现代码:

    public interface RunnableFuture<V> extends Runnable, Future<V> {

        void run();

    }

    可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。

    所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

    事实上,FutureTask是Future接口的一个唯一实现类。

    并发编程的两种实现形式:

    1):使用Callable+Future获取执行结果

    public class Test {
        public static void main(String[] args) {
            ExecutorService executor = Executors.newCachedThreadPool();
            Task task = new Task();
            Future<Integer> result = executor.submit(task);
            executor.shutdown();
             
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
             
            System.out.println("主线程在执行任务");
             
            try {
                System.out.println("task运行结果"+result.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
             
            System.out.println("所有任务执行完毕");
        }
    }
    class Task implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            System.out.println("子线程在进行计算");
            Thread.sleep(3000);
            int sum = 0;
            for(int i=0;i<100;i++)
                sum += i;
            return sum;
        }
    }

    2):使用Callable+FutureTask获取执行结果

    public class Test {
        public static void main(String[] args) {
            //第一种方式
            ExecutorService executor = Executors.newCachedThreadPool();
            Task task = new Task();
            FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
            executor.submit(futureTask);
            executor.shutdown();
             
            //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread
            /*Task task = new Task();
            FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
            Thread thread = new Thread(futureTask);
            thread.start();*/
             
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
             
            System.out.println("主线程在执行任务");
             
            try {
                System.out.println("task运行结果"+futureTask.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
             
            System.out.println("所有任务执行完毕");
        }
    }
    class Task implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            System.out.println("子线程在进行计算");
            Thread.sleep(3000);
            int sum = 0;
            for(int i=0;i<100;i++)
                sum += i;
            return sum;
        }
    }
  • 相关阅读:
    Hdu 1257 最少拦截系统
    Hdu 1404 Digital Deletions
    Hdu 1079 Calendar Game
    Hdu 1158 Employment Planning(DP)
    Hdu 1116 Play on Words
    Hdu 1258 Sum It Up
    Hdu 1175 连连看(DFS)
    Hdu 3635 Dragon Balls (并查集)
    Hdu 1829 A Bug's Life
    Hdu 1181 变形课
  • 原文地址:https://www.cnblogs.com/Candies/p/5692389.html
Copyright © 2011-2022 走看看