如何提升Java并行程序性能

在Java程序中,多线程几乎已经无处不在。与单线程相比,多线程程序的设计和实现略微困难,但经过多线程,咱们却能够得到多核CPU带来的性能飞跃,从这个角度说,多线程是一种值得尝试的技术。那么如何写出高效的多线程程序呢?缓存

  • 有关多线程的误区:线程越多,性能越好网络

很多初学者可能认为,线程数量越多,那么性能应该越好。由于程序给咱们的直观感觉老是这样。一个两个线程可能跑的很难,线程一多可能就快了。但事实并不是如此。由于一个物理CPU一次只能执行一个线程,多个线程则意味着必须进行线程的上下文切换,而这个代价是很高的。所以,线程数量必须适量,最好的状况应该是N个CPU使用N个线程,而且让每一个CPU的占有率都达到100%,这种状况下,系统的吞吐量才发挥到极致。但现实中,不太可能让单线程独占CPU达到100%,一个广泛的愿意是由于IO操做,不管是磁盘IO仍是网络IO都是很慢的。线程在执行中会等待,所以效率就下来了。这也就是为何在一个物理核上执行多个线程会感受效率高了,对于程序调度来讲,一个线程等待时,也正是其它线程执行的大好机会,所以,CPU资源获得了充分的利用。多线程

  • 尽量不要挂起线程并发

多线程程序免不了要同步,最直接的方法就是使用锁。每次只容许一个线程进入临界区,让其它相关线程等待。等待有2种,一种是直接使用操做系统指令挂起线程,另一种是自旋等待。在操做系统直接挂起,是一种简单粗暴的实现,性能较差,不太适用于高并发的场景,由于随之而来的问题就是大量的线程上下文切换。若是能够,尝试一下进行有限的自旋等待,等待不成功再去挂起线程也不迟。这样颇有可能能够避免一些无谓的开销。JDK中ConcurrentHashMap的实现里就有一些自旋等待的实现。此外Java虚拟机层面,对synchronized关键字也有自旋等待的优化。高并发

  • 善用“无锁”性能

阻塞线程会带来性能开销,所以,一种提供性能的方案就是使用无锁的CAS操做。JDK中的原子类,如AtomicInteger正是使用了这种方案。在高并发环境中,冲突较多的状况下,它们的性能远远好于传统的锁操做(《实战Java高并发程序设计》 P158)。优化

  • 处理好“伪共享”问题操作系统

你们知道,CPU有一个高速缓存Cache。在Cache中,读写数据的最小单位是缓存行,若是2个变量存在一个缓存行中,那么在多线程访问中,可能会相互影响彼此的性能。所以将变量存放于独立的缓存行中,也有助于变量在多线程访问是的性能提高(《实战Java高并发程序设计》 P200),大量的高并发库都会采用这种技术。线程

相关文章
相关标签/搜索