`

利用多核CPU计算大的列表中的整数和 CyclicBarrier CountDownLatch ExecutorService

阅读更多

原文:http://flysnow.iteye.com/blog/711162

原文利用了CyclicBarrier、ExecutorService和Callable技术,这些我还不是太懂。将原实现改了一下

 

public class CountListIntegerSum1 {
	private Long sum=0L;//存放整数的和
	private List<Integer> list;//整数集合List
	private int threadCounts;//使用的线程数
	public CountListIntegerSum1(List<Integer> list,int threadCounts) {
		this.list=list;
		this.threadCounts=threadCounts;
	}
	/**
	 * 获取List中所有整数的和
	 */
	public void getIntegerSum(){
		int len=list.size()/threadCounts;//平均分割List
		if(len==0) {
			threadCounts=list.size();//采用一个线程处理List中的一个元素
			len=list.size()/threadCounts;//重新平均分割List
		}
		int tmp = threadCounts;
		for(int i=0;i<tmp;i++) {
			if(i==tmp-1) {//最后一个线程承担剩下的所有元素的计算
				new Thread(new SubIntegerSumTask(list.subList(i*len,list.size()))).start();
			} else {
				new Thread(new SubIntegerSumTask(list.subList(i*len, len*(i+1)>list.size()?list.size():len*(i+1)))).start();
			}
		}
	}
	/**
	 * 分割计算List整数和的线程任务
	 *
	 */
	public class SubIntegerSumTask implements Runnable {
		private List<Integer> subList;
		public SubIntegerSumTask(List<Integer> subList) {
			this.subList=subList;
		}
		public void run() {
			long subSum=0L;
			for (Integer i : subList) {
				subSum += i;
			}
			synchronized(sum) {
				sum+=subSum;
			}
			System.out.println("分配给线程:"+Thread.currentThread().getName()+" 那一部分List的整数和为:"+subSum);
			if(--threadCounts == 0) {
				System.out.println("最后的结果为: ------- " + sum);
			}
		}
	}
	
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        int threadCounts = 10;//采用的线程数
        //生成的List数据   
        for (int i = 1; i <= 1000000; i++) {
            list.add(i);   
        }
        CountListIntegerSum1 countListIntegerSum=new CountListIntegerSum1(list,threadCounts);   
        countListIntegerSum.getIntegerSum();   
    }
}

 

结果 写道
分配给线程:Thread-4 那一部分List的整数和为:45000050000
分配给线程:Thread-8 那一部分List的整数和为:85000050000
分配给线程:Thread-2 那一部分List的整数和为:25000050000
分配给线程:Thread-1 那一部分List的整数和为:15000050000
分配给线程:Thread-6 那一部分List的整数和为:65000050000
分配给线程:Thread-3 那一部分List的整数和为:35000050000
分配给线程:Thread-5 那一部分List的整数和为:55000050000
分配给线程:Thread-0 那一部分List的整数和为:5000050000
分配给线程:Thread-9 那一部分List的整数和为:95000050000
分配给线程:Thread-7 那一部分List的整数和为:75000050000
最后的结果为: ------- 500000500000

 

当然结果还是一样的,这里当所有线程运行完打印出结果,即threadCounts为0时打印。这里还有一个小问题本以为是不是sublist = list.subList(2, 4);就会生成新的list,原来不会。

小提示:list.subList并没有产生新的list

sublist = list.subList(2, 4);这里的sublist 只是RandomAccessSubList,所以对list操作会影响sublist,对sublist操作也会影响list。

public class ListSubList {
	public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        List<Integer> sublist = new ArrayList<Integer>();   
        //生成的List数据   
        for(int i = 1; i <= 10; i++) {
            list.add(i);   
        }
        sublist = list.subList(2, 4);
        System.out.println("sss");
//        sublist.clear();
        list.clear();
        
        System.out.println("sss");
        Iterator i = sublist.iterator();
        while(i.hasNext()) {
        	System.out.println(i.next());
        }
	}
}

 

在eclipse中设置一个断点,很容易可以看出来。

原来作者实现的理解 CyclicBarrier ExecutorService

public class CountListIntegerSum {
	private Long sum=0L;//存放整数的和
	private CyclicBarrier barrier;//障栅集合点(同步器)
	private List<Integer> list;//整数集合List
	private int threadCounts;//使用的线程数
	public CountListIntegerSum(List<Integer> list,int threadCounts) {
		this.list=list;
		this.threadCounts=threadCounts;
	}
	/**
	 * 获取List中所有整数的和
	 * @return
	 */
	public long getIntegerSum(){
		ExecutorService exec=Executors.newFixedThreadPool(threadCounts);
		int len=list.size()/threadCounts;//平均分割List
		//List中的数量没有线程数多(很少存在)
		if(len==0){
			threadCounts=list.size();//采用一个线程处理List中的一个元素
			len=list.size()/threadCounts;//重新平均分割List
		}
		barrier=new CyclicBarrier(threadCounts+1);
		for(int i=0;i<threadCounts;i++){
			//创建线程任务
			if(i==threadCounts-1){//最后一个线程承担剩下的所有元素的计算
				exec.execute(new SubIntegerSumTask(list.subList(i*len,list.size())));
			}else{
				exec.execute(new SubIntegerSumTask(list.subList(i*len, len*(i+1)>list.size()?list.size():len*(i+1))));
			}
		}
		try {
			barrier.await();//关键,使该线程在障栅处等待,直到所有的线程都到达障栅处
		} catch (InterruptedException e) {
			System.out.println(Thread.currentThread().getName()+":Interrupted");
		} catch (BrokenBarrierException e) {
			System.out.println(Thread.currentThread().getName()+":BrokenBarrier");
		}
		exec.shutdown();
		return sum;
	}
	/**
	 * 分割计算List整数和的线程任务
	 * @author lishuai
	 *
	 */
	public class SubIntegerSumTask implements Runnable {
		private List<Integer> subList;
		public SubIntegerSumTask(List<Integer> subList) {
			this.subList=subList;
		}
		
		public void run() {
			long subSum=0L;
			for (Integer i : subList) {
				subSum += i;
			}
			synchronized(sum){//在CountListIntegerSum对象上同步
				sum+=subSum;
			}
			System.out.println("分配给线程:"+Thread.currentThread().getName()+"那一部分List的整数和为:\tSubSum:"+subSum);
			try {
				barrier.await();//关键,使该线程在障栅处等待,直到所有的线程都到达障栅处
			} catch (InterruptedException e) {
				System.out.println(Thread.currentThread().getName()+":Interrupted");
			} catch (BrokenBarrierException e) {
				System.out.println(Thread.currentThread().getName()+":BrokenBarrier");
			}
		}
	}
	
    public static void main(String[] args) {   
        List<Integer> list = new ArrayList<Integer>();   
        int threadCounts = 10;//采用的线程数   
        //生成的List数据   
        for (int i = 1; i <= 1000000; i++) {   
            list.add(i);   
        }
        CountListIntegerSum countListIntegerSum=new CountListIntegerSum(list,threadCounts);   
        long sum=countListIntegerSum.getIntegerSum();   
        System.out.println("List中所有整数的和为:"+sum);   
    }
	
}

 

程序中采用了10个线程来分别计算一个大的list中的所有数的和,利用了CyclicBarrier,这个程序正好展示了如何利用CyclicBarrier,这里在新建CyclicBarrier 时传替了一个11参数进去,就是当有11个线程到达这个樟栅时,才放开所有的线程,让其运行barrier.await();之后的语句。这里正好也比较一下CyclicBarrier 与CountDownLatch(http://xmind.iteye.com/blog/717140)的区别,CyclicBarrier主要可以用于许多线程等待到同一时间点同时发行,CountDownLatch可用于一个线程等待多个线程。显然,这里更适合用CountDownLatch。同时这里还用到了ExecutorService,ExecutorService对于启动新建和启动线程提供了方便。

原来作者实现的理解 ExecutorService.invokeAll()  Callable  Future

public class CountSumWithCallable {

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		int threadCounts =9;//使用的线程数
		long sum=0;
		ExecutorService exec=Executors.newFixedThreadPool(threadCounts);
		List<Callable<Long>> callList=new ArrayList<Callable<Long>>();
		//生成很大的List
		List<Integer> list = new ArrayList<Integer>();
		for (int i = 1; i <= 1000000; i++) {
			list.add(i);
		}
		int len=list.size()/threadCounts;//平均分割List
		//List中的数量没有线程数多(很少存在)
		if(len==0){
			threadCounts=list.size();//采用一个线程处理List中的一个元素
			len=list.size()/threadCounts;//重新平均分割List
		}
		for(int i=0;i<threadCounts;i++){
			final List<Integer> subList;
			if(i==threadCounts-1){
				subList=list.subList(i*len,list.size());
			} else {
				subList=list.subList(i*len, len*(i+1)>list.size()?list.size():len*(i+1));
			}
			//采用匿名内部类实现
			callList.add(new Callable<Long>() {
				public Long call() throws Exception {
					long subSum=0L;
					for(Integer i:subList){
						subSum+=i;
					}
					System.out.println("分配给线程:"+Thread.currentThread().getName()+"那一部分List的整数和为:\tSubSum:"+subSum);
					return subSum;
				}
			});
		}
		List<Future<Long>> futureList=exec.invokeAll(callList);
		for(Future<Long> future:futureList) {
			sum+=future.get();
		}
		exec.shutdown();
		System.out.println(sum);
	}
}

 

最简单直接的一种实现方法,exec.invokeAll负责运行所有的callList,把结果返回到List<Future<Long>> ,程序一直阻塞到所有运行结束。很是适合这种把任务分割出去,最后又要汇总的情况。ExecutorService 不光只是提供了新建启动线程的方法,还提供了返回线程运行结果的方便啊。

 

 

分享到:
评论

相关推荐

    CountDownLatch和CyclicBarrier用法实例大全

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具类,它们用于协调多个线程间的协作。这两个工具都是在`java.util.concurrent`包下,是Java并发库的重要组成部分。 **CountDownLatch** ...

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴 java并发编程中CountDownLatch和CyclicBarrier是两个非常重要的线程控制和调度工具,经常被用于解决多线程程序设计中的线程等待问题。本文将对...

    Java中的CountDownLatch与CyclicBarrier:深入理解与应用实践

    在Java的并发编程中,CountDownLatch和CyclicBarrier是两个非常重要的同步工具,它们用于协调多个线程的执行顺序。本文将详细介绍CountDownLatch和CyclicBarrier的工作原理、使用场景以及如何在实际项目中应用它们。...

    java并发编程中CountDownLatch和CyclicBarrier的使用.pdf

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具,用于协调多个线程之间的交互。它们都属于java.util.concurrent包下的类,为多线程编程提供了强大的支持。 **CountDownLatch** 是一个...

    CountDownLatch 和 CyclicBarrier 的运用(含AQS详解)

    ### CountDownLatch 和 CyclicBarrier 的运用(含AQS详解) #### CountDownLatch **定义与特点:** CountDownLatch 是 Java 并发包中的一个重要组件,它主要用于解决“一个或多个线程等待其他线程完成任务”的问题。...

    精通lambda表达式:Java多核编程

    7. **并发工具类的使用**:包括`ExecutorService`、`CountDownLatch`、`CyclicBarrier`和`Semaphore`等,这些工具可以帮助我们更有效地管理线程和同步,以实现高效的多核编程。 8. **性能优化技巧**:理解并合理...

    详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

    在Java并发编程中,CountDownLatch和CyclicBarrier都是用于协调多线程间同步的重要工具,它们可以帮助开发者在特定条件满足时启动或者结束线程的执行。本文将详细探讨这两个类的内部实现机制以及它们在实际应用场景...

    Java中的CyclicBarrier类最全讲义

    在现代软件开发中,特别是高性能计算领域,利用多核处理器的能力变得至关重要。为了充分利用这些硬件资源,程序员们开始广泛采用并发编程技术。并发编程涉及到同时处理多个任务或数据流,从而提高程序的整体性能。 ...

    多线程与多核编程文档

    在计算机科学领域,多线程和多核编程是提高程序执行效率和系统资源利用率的关键技术。随着硬件技术的发展,多核心处理器已经成为主流,这使得并发处理成为可能,从而实现更高效的计算。本文档将深入探讨多线程和多核...

    CountDownLatch练习

    CountDownLatch是Java并发编程中一个重要的同步工具类,它允许一个或多个线程等待其他线程完成操作。这个工具在多线程环境下的并行处理和协调中扮演着关键角色。 **CountDownLatch是什么?** CountDownLatch是一个...

    Java concurrency之CountDownLatch原理和示例_动力节点Java学院整理

    CountDownLatch是Java并发编程中一个重要的工具类,用于协调多线程间的同步。它由Java并发包`java....在实际编程中,应根据具体需求选择CountDownLatch或CyclicBarrier,以及其他并发工具,以确保程序的正确性和性能。

    CyclicBarrier的用法

    在实际应用中,`CyclicBarrier`常用于分布式计算、多步骤处理等场景,例如在多节点并行计算后需要聚合结果,或者在进行多轮迭代时确保所有工作都在下一轮开始前完成。 总结来说,`CyclicBarrier`是Java并发库中一种...

    CyclicBarrier用法.docx

    CyclicBarrier是Java并发编程中一个非常重要的工具类,它属于java.util.concurrent包,主要用于多线程间的协作,尤其在需要多个线程等待彼此完成特定任务后才能继续执行的场景中发挥着关键作用。CyclicBarrier的名字...

    《Java并发编程艺术》高清带目录中文版

    并发编程是现代软件开发中的重要组成部分,尤其是在服务器端和分布式系统中,它能够充分利用多核处理器的计算能力,提高程序性能。Java作为广泛使用的服务器端开发语言,其并发编程支持非常强大。本书将引领读者探索...

    Java 多线程面试题及答案.pdf

    - **发挥多核CPU的优势**:多线程能让程序在多核CPU上并行执行,充分利用硬件资源,提高程序运行效率。单核CPU虽然可以通过快速线程切换模拟并发,但实际并未真正同时执行,而多核CPU则可以同时处理多个线程。 - *...

    Java中CountDownLatch用法解析

    在主方法中,首先创建了一个固定大小的线程池`ExecutorService`,然后为每个运动员创建一个`Player`对象,并将`begin`和`end`计数器传入,以便它们能够与线程池中的线程进行交互。 当运动员的`run()`方法被调用时,...

    人工智能-项目实践-多线程-多线程与高并发.zip

    在Java中,Java并发工具包(JUC,Java Concurrency Utilities)是处理多线程问题的核心组件,提供了丰富的类和接口,如`Thread`、`ExecutorService`、`Semaphore`、`CountDownLatch`、`CyclicBarrier`等,这些工具...

    28 人齐了,一起行动—CyclicBarrier详解.pdf

    CyclicBarrier 是 Java 并发库中的一种同步工具类,用于协调多个线程之间的协作,使得它们能够一起开始某个计算任务或操作。它的名称“CyclicBarrier”来源于它具有可重用的特点,即当所有等待的线程都达到指定的...

Global site tag (gtag.js) - Google Analytics