该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-07-13
captmjc 写道 来不及看所有的恢复,但是提醒大家注意,在注意算法的同时,注意越界的问题。
两个int相加,都可能越界,何况“很大的List”。所以实战的话,可能需要BigInteger。 而BigInteger的话,更体现了线程的优势。N个较小的BI相加,比一个巨大的BI参与的计算快多了。 同意你说的越界问题,不过采用BigInteger我倒没试过,因为它的加减乘除等操作是程序实现的,不一定比(+-*/)操作符快吧。 |
|
返回顶楼 | |
发表时间:2010-07-13
dilantaya 写道 viei 写道 个人觉的你的这些算法啊,线程操作可能都是白忙活,或者说对这种问题处理的很浅,还不深入。算法挺简单的实现起来也有很多办法,多线程调度什么的也都是基本java知识。
我个人觉的的你要抓住问题的重点,要是用多cpu充分发挥多cpu的优势,首先要把任务分发,你只是起多个线程并不一定操作jvm和操作系统就会把任务分发到多cpu上执行,只有可能时间片切的更小,在执行这些任务。 所以这个过程中考虑的重点应该是 1:操作系统(开多个jvm,规定每个jvm进程运行在指定cpu上,肯定比一个进程下的多个线程只占用一个cpu对多cpu的压榨更好) 2:jvm调整(大数据量必然涉及到垃圾回收) 3:程序编写 上面这些弄好了,再深入一点就考虑,同步消耗问题 cpu多了,同步因素也是决定是否能把多cpu和性能转化率提高出来的一个重要环节。 怎么指定一个jvm对应单个cpu ,高手? 多谢你提出很好的意见。这个就更深入了,我这方便还不太知道,我测试机上只有一个CPU,没法指定,所以只能这么做。你说的方式能不能大概的用代码表示一下,伪代码也行。 |
|
返回顶楼 | |
发表时间:2010-07-13
mapreduce 是什么东东啊!
|
|
返回顶楼 | |
发表时间:2010-07-13
这还是 多线程的问题 啊 还是没有解决多CPU处理的问,你的多线程怎么能保证是多个CPU在处理呢 ,可能还是一个CPU在处理啊 。以前看到过报道好像说是 java7 支持多CPU处理任务。 等待中。。。
|
|
返回顶楼 | |
发表时间:2010-07-13
pengpeng99bill 写道 这还是 多线程的问题 啊 还是没有解决多CPU处理的问,你的多线程怎么能保证是多个CPU在处理呢 ,可能还是一个CPU在处理啊 。以前看到过报道好像说是 java7 支持多CPU处理任务。 等待中。。。
可能,你误会了。Java 1.2之后,使用的操作系统内核线程,操作系统还是会利用多CPU的,也就是说和Java无关了。 我的《Java内存模型》正在写,其中起到了这些东西,如果有需要的话,可以关注一下。 |
|
返回顶楼 | |
发表时间:2010-07-13
如果我做的话,这就是一个分治合并的思想在里面。
分多少完全看你线程数目 一般来说我们完全可以开2N + 1个线程来做运算 你可以使用CountDownLatch,信号量,或者你提到的栅栏都可以。 有个漏斗理论不知道你看过没有,合并的任务就好像漏斗一样。。 |
|
返回顶楼 | |
发表时间:2010-07-13
dilantaya 写道 viei 写道 个人觉的你的这些算法啊,线程操作可能都是白忙活,或者说对这种问题处理的很浅,还不深入。算法挺简单的实现起来也有很多办法,多线程调度什么的也都是基本java知识。
我个人觉的的你要抓住问题的重点,要是用多cpu充分发挥多cpu的优势,首先要把任务分发,你只是起多个线程并不一定操作jvm和操作系统就会把任务分发到多cpu上执行,只有可能时间片切的更小,在执行这些任务。 所以这个过程中考虑的重点应该是 1:操作系统(开多个jvm,规定每个jvm进程运行在指定cpu上,肯定比一个进程下的多个线程只占用一个cpu对多cpu的压榨更好) 2:jvm调整(大数据量必然涉及到垃圾回收) 3:程序编写 上面这些弄好了,再深入一点就考虑,同步消耗问题 cpu多了,同步因素也是决定是否能把多cpu和性能转化率提高出来的一个重要环节。 怎么指定一个jvm对应单个cpu ,高手? 在linux下你看一下cpuinfo获取cpu信息,编号 然后启动的时候和运行的时候都可以通过taskset命令进行cpu绑定 如果开多进程处理,那么进程间数据如何共享,这个还要重新考虑 你现在的程序都是单进程下的 |
|
返回顶楼 | |
发表时间:2010-07-13
最后修改:2010-07-13
package com.wl.test.concurrent.semaphore; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; /** * * 有一个很大的整数list,需要求这个list中所有整数的和,写一个可以充分利用多核CPU的代码,来计算结果。 * * * 乍一看到题目“充分利用多核CPU”, * 以为会根据CPU的核心数,计算出比较合理的任务线程的数目。 * 就题目的计算目标来说,实际上讲的主线程等待任务线程完成, * 任务线程之间没有必要互相等待。 * 是不是可以考虑用信号来...... * 每次来看帖,都发现大家图画的很拉风…… * * 我也帖个代码,虽然来晚了,大家不一定能看到…… * * @author HardPass * */ public class BigListSumWithSemaphore { private List<Integer> list = new ArrayList<Integer>(); private AtomicLong sum = new AtomicLong(0L); // 结果 private int threadCounts = 2 * Runtime.getRuntime().availableProcessors() + 1; // 任务线程数 private List<Runnable> tasks = new ArrayList<Runnable>(); // 任务线程 SemaphoreLock lock = new SemaphoreLock(); public static void main(String[] args) { new BigListSumWithSemaphore().test(); } public void test() { init(); ExecutorService exec = Executors.newFixedThreadPool(threadCounts); //线程池 for(Runnable task : tasks){ exec.execute(task); } lock.lockHere(); // 此处尝试wait exec.shutdown(); System.out.println("List中所有整数的和为:" + sum); } private void init() { for (int i = 1; i <= 1000000; i++) { list.add(i); } int len = list.size() / threadCounts; int i = 0; for (; i < threadCounts - 1; i++) { tasks.add(new Task(list.subList(i * len, (i + 1) * len))); } tasks.add(new Task(list.subList(i * len, list.size()))); } private class Task implements Runnable { private List<Integer> subList; public Task(List<Integer> subList) { this.subList = subList; } @Override public void run() { lock.lockThere(); // 增加锁的计数 long subSum = 0L; for (Integer i : subList) { subSum += i; } sum.addAndGet(subSum); System.out.println("分配给线程:" + Thread.currentThread().getName() + "那一部分List的整数和为:\tSubSum:" + subSum); lock.release(); // 释放一个锁的计数 } } } /** * * 信号量锁 * * 此Semaphore非java.util.concurrent.Semaphore * * @author HardPass * */ class SemaphoreLock { private int count = 0; // 信号量 /** * 信号量大于0的时候 wait * 这是不是传说中的可重入? */ public synchronized void lockHere() { while (count > 0) { try { wait(); } catch (InterruptedException e) { } } } public synchronized void lockThere() { count++; } public synchronized void release() { count--; if(count==0){ notify(); } } } |
|
返回顶楼 | |
发表时间:2010-07-13
hardPass 写道 package com.wl.test.concurrent.semaphore;
import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; /** * * 乍一看到题目“充分利用多核CPU”, * 以为会根据CPU的核心数,计算出比较合理的任务线程的数目。 * 就题目的计算目标来说,实际上讲的主线程等待任务线程完成, * 任务线程之间没有必要互相等待。 * 是不是可以考虑用信号来...... * 每次来看帖,都发现大家图画的很拉风…… * * 我也帖个代码,虽然来晚了,大家不一定能看到…… * * @author HardPass * */ public class BigListSumWithSemaphore { private List<Integer> list = new ArrayList<Integer>(); private AtomicLong sum = new AtomicLong(0L); // 结果 private int threadCounts = 2 * Runtime.getRuntime().availableProcessors() + 1; // 任务线程数 private List<Runnable> tasks = new ArrayList<Runnable>(); // 任务线程 SemaphoreLock lock = new SemaphoreLock(); public static void main(String[] args) { new BigListSumWithSemaphore().test(); } public void test() { init(); ExecutorService exec = Executors.newFixedThreadPool(threadCounts); //线程池 for(Runnable task : tasks){ exec.execute(task); } lock.lockHere(); exec.shutdown(); System.out.println("List中所有整数的和为:" + sum); } private void init() { for (int i = 1; i <= 1000000; i++) { list.add(i); } int len = list.size() / threadCounts; int i = 0; for (; i < threadCounts - 1; i++) { tasks.add(new Task(list.subList(i * len, (i + 1) * len))); } tasks.add(new Task(list.subList(i * len, list.size()))); } private class Task implements Runnable { private List<Integer> subList; public Task(List<Integer> subList) { this.subList = subList; } @Override public void run() { lock.lockThere(); long subSum = 0L; for (Integer i : subList) { subSum += i; } sum.addAndGet(subSum); System.out.println("分配给线程:" + Thread.currentThread().getName() + "那一部分List的整数和为:\tSubSum:" + subSum); lock.release(); } } } /** * * 信号量锁 * * 此Semaphore非java.util.concurrent.Semaphore * * @author HardPass * */ class SemaphoreLock { private int count = 0; // 信号量 /** * 信号量大于0的时候 wait * 这是不是传说中的可重入? */ public synchronized void lockHere() { while (count > 0) { try { wait(); } catch (InterruptedException e) { } } } public synchronized void lockThere() { count++; } public synchronized void release() { count--; if(count==0){ notify(); } } } java不是有Semaphore,为啥你非要自己写个lock |
|
返回顶楼 | |
发表时间:2010-07-13
amigo 写道 dilantaya 写道 sunwenran 写道 赞一个。
问题是我用你的例子比较直接加 long noCurrentSum=0L; for(Integer i:list){ noCurrentSum+=i; } 发现时间差不多。而且有时候直接加更快。纠结了。。我的是双核。 可能是你给的数据量还不够大 调整到50000000 for (int i = 1; i <= 50000000; i++) { list.add(i); } 单线程时间比并发更快 呵呵其实这种纯粹的算术相加速度单线程和多线程是一样的(因为没有io读写,没有网络等待等等,),新建线程还要消耗资源,如何设计利用多核cpu就涉及到jvm的底层实现了,所以要我回答这个问题,我给出下面答案: int sum=0; for(int i=0;i<list.size();i++) { sum+=list.get(i); } return sum; |
|
返回顶楼 | |