1. 多线程场景下尽量使用并发容器代替同步容器

  (如ConcurrentHashMap代替同步且基于散列的Map, 遍历操作为主要操作的情况下用CopyOnWriteArrayList代替同步的List)

  ConcurrentHashMap:分段锁机制,多线程条件下优于HashMap+synchronized的组合方式;
  CopyOnWriteArrayList: 每次修改时都会创建并重新发布一个新的容器副本,从而实现可变性。容器的迭代器保留一个指向底层基础数组的引用,这个数组当前位于迭代器的起始位置,由于他不会被修改,
所以在对其进行同步时只需确保数组内容的可见性。
2. 避免死锁
  a)尽量不要在释放锁之前竞争其他锁:一般可以通过细化同步方法来实现,只在真正需要保护共享资源的地方去拿锁,并尽快释放锁,这样可以有效降低在同步方法里调用其他同步方法 的情况
  b)顺序索取锁资源: 如果实在无法避免嵌套索取锁资源,则需要制定一个索取锁资源的策略,先规划好有哪些锁,然后各个线程按照一个顺序去索取
  c)尝试定时锁: Java 5提供了更灵活的锁工具,可以显式地索取和释放锁。那么在索取锁的时候可以设定一个超时时间,如果超过这个时间还没索取到锁,则不会继续堵塞而是放弃此次任务,如下:

public boolean trySendOnSharedLine(String message, long timeout, TimeUnit unit) throws InterruptedException {
long nanosToLock = unit.toNanos(timeout) - estimatedNanosToSend(message);
if (!lock.tryLock(nanosToLock, NANOSECONDS)){
return false;
}
try {
return sendOnSharedLine(message);
} finally {
lock.unlock();
}
} 

这样可以效打破死锁条件。
3. Amdahl定理:
  speedup<= 1/(F+(1-F)/N)
  其中,F是串行化比例,N是处理器数量,由上可知,只有尽可能减少串行化,才能最大化地提高可扩展能力。降低串行化的关键就是降低锁竞争,当很多并行任务挂在锁的获取上,就是串行化的表现.
4. 降低锁竞争
  1)缩小锁的范围
    尽量缩小锁保护的范围,快进快出,因此尽量不要直接在方法上使用synchronized关键字,而只是在真正需要线程安全保护的地方使用
  2)减小锁的粒度
    尽量避免大段的synchronize代码块
  3)减少共享资源的依赖
    在多线程开发中尽量减少对共享资源的依赖,比如对象池的技术应该慎重考虑,新的JVM对新建对象以做了足够的优化,性能非常好,如果用对象池不但不能提高多少性能,反而 会因为锁竞争导致降低线程的可并发性。
  4)使用读写分离锁来替换独占锁
    Java 5提供了一个读写分离锁(ReadWriteLock)来实现读-读并发,读-写串行,写-写串行的特性。这种方式更进一步提高了可并发性,因为有些场景大部分是读操作,因此没必要串行工作。
5. 切换上下文
  线程比较多的时候,操作系统切换线程上下文的性能消耗是不能忽略的,
6. 内存同步
  当使用到synchronized、volatile或Lock的时候,都会为了保证可见性导致更多的内存同步,这就无法享受到JMM结构带来了性能优化。
7. 适当使用同步工具类
  (1) 闭锁(CountDownLatch): 延迟线程的进度直到其达到终止状态,用来确保某些活动直到其他活动都完成后才继续执行;一次性对象,一旦进入终止状态,就不能被重置;
  (2) FutureTask: 可生成结果的Callable,如果有结果可用,那么FutureTask.get将立即返回结果,否则它会一直阻塞,直到结果计算出来再将其返回。
  (3) 信号量(Semaphore):用来控制同时访问某个特定资源的操作数量,或者同时某个指定操作的数量,Semaphore还可以用来实现某种资源池,或者对容器施加边界。
  (4) 栅栏(Barrier): 类似于闭锁,区别在于所有线程必须同时到达栅栏位置才能继续执行,闭锁用于等待事件,而栅栏用于等待其他线程。可被重置用于下次使用。两种实现方式:CyclicBarrier,Exchanger

8. 实际情况中,应尽可能的使用现有的线程安全对象(例如AtomicInteger)来管理类的状态

9. 在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非用volatile来声明它们,或者用锁保护起来。

JAVA并发编程学习笔记------多线程调优的更多相关文章

  1. Java并发编程学习笔记

    Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...

  2. Java并发编程学习笔记 深入理解volatile关键字的作用

    引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识.网上关于volatile的 ...

  3. Java 并发编程学习笔记 理解CLH队列锁算法

    CLH算法实现 CLH队列中的结点QNode中含有一个locked字段,该字段若为true表示该线程需要获取锁,且不释放锁,为false表示线程释放了锁.结点之间是通过隐形的链表相连,之所以叫隐形的链 ...

  4. Java并发编程学习笔记(一)——线程安全性

    主要概念:线程安全性.原子性.原子变量.原子操作.竟态条件.复合操作.加锁机制.重入.活跃性与性能. 1.当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变 ...

  5. JAVA并发编程学习笔记------对象的可见性及发布逸出

    一.非原子的64位操作: 当线程在没有同步的情况下读取变量时,可能会得到一个失效值,但至少这个值是由之前某个线程设置的值,而不是一个随机值,这种安全性保证被称为最低安全性.最低安全性适用于绝大多数变量 ...

  6. [转]JAVA并发编程学习笔记之Unsafe类

    1.通过Unsafe类可以分配内存,可以释放内存:类中提供的3个本地方法allocateMemory.reallocateMemory.freeMemory分别用于分配内存,扩充内存和释放内存,与C语 ...

  7. Java并发编程学习笔记(三)——对象的组合

    重要概念: 1.在设计线程安全类的过程中,需要包含以下三个基本要素: (1)找出构成对象状态的所有变量. (2)找出约束状态变量的不变性条件. (3)建立对象状态的并发访问管理策略. 2.

  8. Java并发编程学习笔记(二)——对象的共享

    主要概念:可见性.重排序.失效数据.最低安全性.发布.逸出.线程封闭(Ad-hoc.栈封闭.ThreadLocal类).不变性.Final域.事实不可变对象. 1.在没有同步的情况下,编译器.处理器以 ...

  9. java并发编程学习笔记(一)初识并发原子性

    1.并发的意义 现在是一个多核的时代,并发的存在意义就是为了能够充分利用多核计算机的优势,提高程序的运行效率: 2.并发的风险 竞争-----多个线程对内存数据数据进行读写操作时,对数据处理结果的一个 ...

随机推荐

  1. 类里面的非static const成员

    类里面的成员变量可以用const修饰,在只用const不用static修饰的情况下,这种使用的限制比较多 (1)不能定义处初始化,必须在类的构造函数初始化列表里面初始化(虽然在vs中,可以在定义处初始 ...

  2. C语言基础第二次作业

    PTA第一次作业 题目7-1  统计学生成绩 1.实验代码 #include<stdio.h> int main(void){ ,B=,C=,D=,E=,f; scanf("%d ...

  3. sql server 2008安装的时候选NT AUTHORITY\NEWORK SERVICE 还是选 NT AUTHORITY\SYSTEM ?

    sql server 2008安装的时候选NT AUTHORITY\NEWORK SERVICE 还是选 NT AUTHORITY\SYSTEM ? sql server 2008安装的时候选NT A ...

  4. hdu-1179(匈牙利算法)

    题目链接: 思路:找n个巫师和m个魔棒匹配的问题,匈牙利算法模板 匈牙利算法:https://blog.csdn.net/sunny_hun/article/details/80627351 #inc ...

  5. SPSS--回归-多元线性回归模型案例解析

    多元线性回归,主要是研究一个因变量与多个自变量之间的相关关系,跟一元回归原理差不多,区别在于影响因素(自变量)更多些而已,例如:一元线性回归方程 为: 毫无疑问,多元线性回归方程应该为: 上图中的 x ...

  6. HTML中submit和button的区别

    submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了. 如果表单在点击提交按钮后需要用JS进行处理(包括输入验证)后再提交的话,通常都必须把submit改成butt ...

  7. Chrome报错:跨域问题处理( Access-Control-Allow-Origin)_ 用于本地测试的快捷解决方法

    报错提示如下: XMLHttpRequest cannot load http://www.xxxx.com/264/Data/GetScreenInfo. No 'Access-Control-Al ...

  8. 一次简单完整的自动化登录测试-基于python+selenium进行cnblog的自动化登录测试

    Web登录测试是很常见的测试,手动测试大家再熟悉不过了,那如何进行自动化登录测试呢!本文就基于python+selenium结合unittest单元测试框架来进行一次简单但比较完整的cnblog自动化 ...

  9. Python + Robotframework + Appium 之APP自动化测试实践(二)

    废话不多说,直接来实践(二),本次基于Android手机Settings模块下的search功能进行的自动化测试,代码如下 : *** Settings *** Library AppiumLibra ...

  10. Media Queries简单案例一

    案例一: 1 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" ...