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

  1. 有关多线程的误区:线程越多,性能越好

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

  1. 尽可能不要挂起线程

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

  1. 善用“无锁”

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

  1. 处理好“伪共享”问题

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

参考:

如何提高Java并行程序性能??的更多相关文章

  1. Java并发程序设计(二)Java并行程序基础

    Java并行程序基础 一.线程的生命周期 其中blocked和waiting的区别: 作者:赵老师链接:https://www.zhihu.com/question/27654579/answer/1 ...

  2. JAVA并行程序基础

    JAVA并行程序基础 一.有关线程你必须知道的事 进程与线程 在等待面向线程设计的计算机结构中,进程是线程的容器.我们都知道,程序是对于指令.数据及其组织形式的描述,而进程是程序的实体. 线程是轻量级 ...

  3. JAVA并行程序基础二

    JAVA并行程序基础二 线程组 当一个系统中,如果线程较多并且功能分配比较明确,可以将相同功能的线程放入同一个线程组里. activeCount()可获得活动线程的总数,由于线程是动态的只能获取一个估 ...

  4. JAVA并行程序基础一

    JAVA并行程序基础一 线程的状态 初始线程:线程的基本操作 1. 新建线程 新建线程只需要使用new关键字创建一个线程对象,并且用start() ,线程start()之后会执行run()方法 不要直 ...

  5. Java并行程序设计模式小结

    这里总结几种常用的并行程序设计方法,其中部分文字源自<Java程序性能优化>一书中,还有部分文字属于个人总结,如有不对,请大家指出讨论. Future模式 一句话,将客户端请求的处理过程从 ...

  6. Java面试题系列 提高Java I/O 性能

    1.提高java的 i/o性能.. http://blog.csdn.net/cherami/article/details/3854 我们知道Java中一般的输入输出流都是用单字节的读取方法来进行I ...

  7. 在 NetBeans IDE 6.0 中分析 Java 应用程序性能

    NetBeans IDE 6.0 包含一个强大的性能分析工具,可提供与应用程序运行时行为有关的重要信息.通过 NetBeans 性能分析工具,我们可以方便地在 IDE 中监控应用程序的线程状态.CPU ...

  8. 第2章 Java并行程序基础(三)

    2.8 程序中的幽灵:隐蔽的错误 2.8.1 无提示的错误案例 以求两个整数的平均值为例.请看下面代码: int v1 = 1073741827; int v2 = 1431655768; Syste ...

  9. ASP.NET Core如何使用压缩中间件提高Web应用程序性能

    前言 压缩可以大大的降低我们Web服务器的响应速度,压缩从而提高我们网页的加载速度,以及节省一定的带宽. 何时使用相应压缩中间件 在IIS,Apache,Nginx中使用基于服务端的响应压缩技术.中间 ...

随机推荐

  1. sqlplus连接oracle失败分析和解决

    背景: 多台Linux服务器需要安装Oracle客户端,实现和Oracle数据库连接做业务处理. 安装完第一台后,直接将安装的目录压缩并复制到其他几台机器上,启动sqlplus连接数据库时,一直提示输 ...

  2. H5案例分享:移动端滑屏 touch事件

    移动端滑屏 touch事件 移动端触屏滑动的效果的效果在电子设备上已经被应用的越来越广泛,类似于PC端的图片轮播,但是在移动设备上,要实现这种轮播的效果,就需要用到核心的touch事件.处理touch ...

  3. JDK source 之 ArrayList 需要注意事项

    线程安全 ArrayList内部没有实现原子性操作,所以是非线程安全的.如果需要在线程安全的环境下使用List的话,需要使用Vector 或者CopyOnWriteArrayList,具体场景,自行深 ...

  4. Ubuntu 登录锐捷 网卡被禁用 网口灯不亮解决

    cd rjsupplicantchmod +x rjsupplicant.sh sudo ./rjsupplicant.sh -u username-p password -d 1 sudo serv ...

  5. 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(转)

    我们将ASP.NET程序从IIS6移植到IIS7,可能运行提示以下错误: HTTP 错误 500.23 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.N ...

  6. mysql存储过程中 乱码问题解决办法

    中文乱码无论在何时都是一个头疼的问题,mysql的存储过程参数也同样存在这个问题.1.直接使用insert into语句没问题,能够正常插入汉字.2.把insert into语句移到Procedure ...

  7. Spring Security控制权限

    Spring Security控制权限 1,配置过滤器 为了在项目中使用Spring Security控制权限,首先要在web.xml中配置过滤器,这样我们就可以控制对这个项目的每个请求了. < ...

  8. 开发ios的语言

    iOS发展这么多年了,很多第三方语言都向开发一种自己的iOS,于是多种跨平台诞生了! Object-c.swift: 当然是开发iOS的首先,毕竟是苹果自己的东西,也是最流行.最适合开发ios的,无论 ...

  9. [Android Pro] 完美解决隐藏Listview和RecyclerView去掉滚动条和滑动到边界阴影的方案

    reference to : http://blog.csdn.net/ming2316780/article/details/51578621 一.首先是Listview的属性设置 设置滑动到顶部和 ...

  10. swap的应用两个数的交换

    #include <stdio.h>//这儿表示的函数的输入输出头文件void swap(int x,int y);void swap_p(int *x,int *y);//表示调用一个方 ...