多线程实现数组求和

多线程实现数组求和


多线程学习
类型一 修改传入线程的数组引用的值,完成后循环累加数组。
public class SumNumber implements Runnable{
    private int[] sum;
    private int formInt;
    private int intoInt;
    private int threadNo;

    public SumNumber(int[] sum, int formInt, int intoInt, int threadNo){
        this.sum = sum;
        this.formInt = formInt;
        this.intoInt = intoInt;
        this.threadNo = threadNo;
    }

    @Override
    public void run() {
        int  su = 0;
        for(int i = formInt;i<=intoInt;i++){
            su+=i;
        }
        sum[threadNo] = su;
    }

    public static void main(String[] args) throws InterruptedException {
    	//1-10000求和
        Integer max = 10000;
        Integer resSum = 0;
        int threads = 4;
        int[] sumArray = new int[threads];
        for(int i=0;i
类型二 通过callback 返回累加的值 直接相加
方法一 使用ExecutorService 的方式

获取数据的时候会按照线程添加的顺序获取 如果上一个没有完成 会堵塞直到完成才会获取下一个线程的数据

newCachedThreadPool()

-缓存型池子,先查看池中有没有以前建立的线程,如果有,就 reuse.如果没有,就建一个新的线程加入池中
-缓存型池子通常用于执行一些生存期很短的异步型任务
因此在一些面向连接的daemon型SERVER中用得不多。但对于生存期短的异步任务,它是Executor的首选。
-能reuse的线程,必须是timeout IDLE内的池中线程,缺省 timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。
注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。

newFixedThreadPool(int)

-newFixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程
-其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子
-和cacheThreadPool不同,FixedThreadPool没有IDLE机制(可能也有,但既然文档没提,肯定非常长,类似依赖上层的TCP或UDP IDLE机制之类的),所以FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器
-从方法的源代码看,cache池和fixed 池调用的是同一个底层 池,只不过参数不同:
fixed池线程数固定,并且是0秒IDLE(无IDLE)
cache池线程数支持0-Integer.MAX_VALUE(显然完全没考虑主机的资源承受能力),60秒IDLE

newScheduledThreadPool(int)

-调度型线程池
-这个池子里的线程可以按schedule依次delay执行,或周期执行

SingleThreadExecutor()

-单例线程,任意时间池中只能有一个线程
-用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)

public class ThreadSumCallBack implements Callable {

    private int[] numbers;
    private int start;
    private int end;

    public ThreadSumCallBack(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];
        }
        return sum;
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //获取处理器个数
        int cpuNumber = Runtime.getRuntime().availableProcessors();
        ExecutorService exse = Executors.newFixedThreadPool(cpuNumber);
        List> tasks = new ArrayList<>();
        int[] numbers = new int[10000];
        for(int i = 1;i <= numbers.length; i++){
            numbers[i-1] = i;
        }
        for(int i = 0;i < cpuNumber; i++){
            int start = numbers.length / cpuNumber * i;
            int end = numbers.length / cpuNumber * (i + 1);
            if(end > numbers.length){
                end = numbers.length;
            }
            ThreadSumCallBack sb = new ThreadSumCallBack(numbers, start, end);
            FutureTask task = new FutureTask<>(sb);
            tasks.add(task);
            if(!exse.isShutdown()){
                exse.submit(task);
            }
        }
        int res = 0;
        for(Future ta : tasks){
            Long a = ta.get();
            res+=a;
        }
        exse.shutdown();
        System.out.println(res);

    }
}
方法二 使用CompletionService的方式

CompletionService内部维护了一个阻塞队列,会按照执行完成的顺序添入队,这样迭代获取线程数据的时候就会按照执行完成的顺序获取,不会出现上一个线程没有完成就获取不到下一个已经完成的线程的数据了

public class ThreadSumCallBack implements Callable {

    private int[] numbers;
    private int start;
    private int end;

    public ThreadSumCallBack(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];
        }
        return sum;
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //获取处理器个数
        int cpuNumber = Runtime.getRuntime().availableProcessors();
        ExecutorService exse = Executors.newFixedThreadPool(cpuNumber);
        CompletionService completionService = new ExecutorCompletionService(exse);
//        List> tasks = new ArrayList<>();
        int[] numbers = new int[10000];
        for(int i = 1;i <= numbers.length; i++){
            numbers[i-1] = i;
        }
        for(int i = 0;i < cpuNumber; i++){
            int start = numbers.length / cpuNumber * i;
            int end = numbers.length / cpuNumber * (i + 1);
            if(end > numbers.length){
                end = numbers.length;
            }
            ThreadSumCallBack sb = new ThreadSumCallBack(numbers, start, end);
//            FutureTask task = new FutureTask<>(sb);
//            tasks.add(task);
            if(!exse.isShutdown()){
                completionService.submit(sb);
            }
        }
        int res = 0;
        for(int i = 0; i< cpuNumber; i++){
            Long a =  completionService.take().get();
            res+=a;
        }
        exse.shutdown();
        System.out.println(res);

    }
}

你可能感兴趣的:(多线程实现数组求和)