lanxiazhi 写道
看过主贴和评论,学习了。
发现的问题:
(1)CyclicBarrier不适合这种并发任务。单个线程完成任务之后完全可以终止了,没必要全部等待着,这可能是很大的资源浪费。使用CountDownLatch也会有这个问题。
(2)楼主使用了线程同步,考虑到同步的代价,这是可能是个很大的时间浪费。
(3)楼主使用CyclicBarrier的唯一用处在于,保证所有的任务都完成了。但是杀鸡焉用牛刀?这可能是...的浪费
其实实现这样的功能,可以不用那么复杂,而且可以不用加锁。这里需要一个AtomicInteger(设为atom)。每个线程获得自己的sublist求和任务之后,计算一个和,保存到某个成员变量(设为subsum)中(如某楼上所说),把那个atom加1,然后结束。
在主方法中,启动所有线程,然后添加一条语句,等待所有线程完成任务:
while(atom.intValue()<threadCounts)
Thread.yield();
最后从所有死掉的线程对象中,获取subsum并累加即可。
我比较同意lanxianzhi的说法。
使用CountDownLatch,其他所有的计算线程都在计算,最后输出的线程肯定在等所有的线程算好才行。
更进一步的问题是:如果我想知道目前算好的实时总数是多少,以及目前多少个线程已经算好了,那么使用CountDownLatch是没有办法的。
比如,有10000个计算线程,一个输出线程在wait,输出线程只能等10000个计算线程都计算完,wait才会结束,然后才能输出。只有一次输出。
也许你想在计算的线程里面把目前被同步的sum给实时打印出来,这样每个计算线程计算结束之后就把当时的实时的结果打印出来,那么计算线程就不符合单一责任原则了。
对于目前已经完成多少个任务,再加个线程共享的变量(任务完成计数器)来自增也不好。
就算用上AtomicInteger也是一种负担。
所以我不觉得应该使用CountDownLatch
线程同步synchronized是不需要的,用AtomicInteger会快一些。
CyclicBarrier就更不需要了,我没有写代码测试,但是按照我的理解,如果你开启11个线程,10个线程在计算,1个线程等待输出,只有当所有线程都执行到await()才能继续。
如果你开的线程就上千个,那么且不是上千个线程都在那边等待?
我还是推荐使用ExecutorCompleteionService
1. ExecutorCompleteionService可以随时拿到完成计算的线程的结果,然后在这个基础上继续进行加运算,而且不需要创建一个在线程之间共享的变量,每个线程有自己的结果变量,这个变量最终会作为task的结果之一返回。
2. 可以随时知道完成的计算线程的计数,当然需要ExecutorCompleteionService执行够快才行,如果计算线程执行很快就结束的话,完成的线程数会不准
我没有在机子上试
贴个Java核心技术的例子代码
ExecutorCompleteionService service = new ExecutorCompleteionService(executor);
for(Callable<Integer> task : tasks) {
service.submit(task);
}
for(int i = 0; i < tasks.size(); i++) {
count += service.take().get();// 如果有线程返回,马上可以得到结果,如果没有任何线程返回,阻塞等待结果
}
这里不需要sum这个所有的线程都共享的变量。因此也不需要同步或者AtomicInteger。
分享到:
相关推荐
2. **丰富的库支持**:Python 拥有庞大的标准库和第三方库,几乎涵盖了所有应用领域,如网络编程、图形用户界面、科学计算等。 3. **跨平台性**:Python 可以运行在多种操作系统上,如 Windows、Linux 和 macOS 等。...
### Delphi 面试题知识点解析 #### 一、基础知识题解析 1. **Delphi 是什么?它主要应用于什么领域?** - **Delphi** 是一种基于 Object Pascal 的集成开发环境(IDE),主要用于 Windows 平台上的应用程序开发。...
- **作用**: 由于GIL的存在,在多线程环境下,即使CPU有多核也无法充分利用多核的优势,因为同一进程中只有一个线程可以执行Python字节码。 - **影响**: 对于I/O密集型的应用,GIL的影响较小,但对于CPU密集型任务...
根据给定文件的信息,我们可以总结出一系列与Python相关的面试题及其答案。这些问题涵盖了Python的基本语法、数据类型、高级特性等多个方面。接下来,我们将详细解析这些知识点。 ### 模块和包的区别 在Python中,...
Python也提供了多线程和多进程支持,以便更好地利用多核处理器。 6. 全局解释器锁(GIL) Python中的全局解释器锁(GIL)是为了简化内存管理而设计的,它限制了同一时刻只有一个线程可以执行Python字节码。这意味着...
- 利用多进程可以充分利用多核CPU资源。 7. **深拷贝与浅拷贝** - 深拷贝创建一个全新的对象,而浅拷贝仅复制对象的引用。 - 当原对象被修改时,深拷贝的对象不受影响,而浅拷贝的对象可能会受到影响。 8. **is...
### Python面试题详解 #### 1. Python的函数参数传递 在Python中,函数参数的传递遵循“传值”而非“传引用”的原则。当传递不可变数据类型(如整数、字符串等)时,实际上是将该数据类型的值复制一份传递给函数;...
51. Java 8的ConcurrentHashMap弃用分段锁是因为分段锁在多核CPU环境下性能瓶颈,改为使用CAS和Node链表实现。 52. ConcurrentHashMap使用synchronized而非ReentrantLock是因为减少锁粒度,提高并发性能。 53. ...
通过在同一台机器上启动多个Redis实例,可以充分利用多核资源。 3. **Redis的性能优势**: - **速度**:由于数据存储在内存中,Redis的读写速度非常快,接近O(1)的时间复杂度。 - **丰富的数据类型**:支持多种...
这限制了多核CPU下的并行计算能力,但在IO密集型任务中,多线程仍然能提高效率。 - 使用`threading`库可以创建线程,但需要注意GIL的存在可能导致多线程不如预期中的并行。 以上是Python面试中常见的知识点,理解...