多线程并发的最佳实践总结

使用本地变量

  1. 优先考虑使用本地变量,避免创建一个类或实例的变量;
  2. 这样可以节省内存,并进行复用;

    使用不可变类

    降低代码中需要的同步变量,充分利用JVM提供的功能。

最小化锁的作用域范围

大名鼎鼎的阿姆达尔定律,表达式为:

S=1/(1-a+a/n)

其中:
a是并行计算部分所占的比例,
n是并行计算所处理的结点个数,
S是最终的加速比。

当1-a=0时,(即没有串行,只有并行)最大加速比s=n;当a=0时(即只有串行,没有并行),最小加速比s=1;当n→∞时,极限加速比s→ 1/(1-a),这也就是加速比的上限。例如,若串行代码占整个代码的25%,则并行处理的总体性能不可能超过4。

使用线程池的Executor

避免new Thread创建线程。通过线程池的管理,尅提高线程的复用性(避免新建线程的昂贵的资源消耗),简化线程生命周期的管理。

避免使用线程的wait()和notify()

优先考虑使用线程的辅助工具类,宁可使用同步也不使用线程的wait()和notify()方法。因为线程间的通讯会消耗较多的系统资源。

使用BlockingQueue实现生产者-消费者模式

阻塞队列是生产者-消费者模式的最好的实现方式,不仅包括单个生产者单个消费者,还支持多个生产者多个消费者情况。

优先使用并发集合

JDK提供了ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet、BlockingQueue中的Deque和BlockingDeque五大并发集合,他们有着较好性能;宁使用该并发集合,而避免使用synchronizedXXX的锁同步集合。

使用Semaphore创建有界的访问

为了建立可靠稳定的系统,对数据库、文件系统、SOCKET的访问需进行有界的控制。

尽量减少同步方法使用

  1. 宁可使用同步代码块,也要尽量减少同步方法使用。
  2. 其中synchronized关键字标识方法时,所有调用到该方法的域都会被JVM进行锁定监督.
  3. 使用synchronized 同步代码块只会锁定一个对象,而不会将当前整个方法锁定;如果更改共同的变量或类的字段,优先选择原子性变量,其次使用volatile。如果你需要互斥锁,可以考虑使用ReentrantLock。

避免使用静态变量

静态变量在多线程并发环境中会造成较多的问题。当使用静态变量时,优先将其指定为final变量,若用其来保存集合Collection变量,则考虑使用只读集合。

SupriseMF wechat
欢迎关注微信订阅号【星球码】,分享学习编程奇淫巧技~
喜欢就支持我呀(*^∇^*)~

热评文章