Java多线程知识小抄集(四)——完结

本文主要整理博主遇到的Java多线程的相关知识点,适合速记,故命名为“小抄集”。本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆。

更多内容可以查阅:
Java多线程知识小抄集(一)
Java多线程知识小抄集(二)
Java多线程知识小抄集(三)

68. 如何避免死锁

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,他们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足一下4个条件:
互斥条件:一个资源每次只能被一个进程使用。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序做操作来避免死锁。

69. 怎么检测一个线程是否拥有锁

java.lang.Thread中有一个方法:public static native boolean holdsLock(Object obj). 当且仅当当前线程拥有某个具体对象的锁时返回true

70. 如何查看线程快照?

jstack命令用来生成虚拟机当前的线程快照信息,线程快照就是当前虚拟机每一个线程正在执行的方法对战的集合。生成线程快照的目的主要是为了定位线程长时间没有响应的原因,如线程死锁、网络请求没有设置超时时间而长时间没有返回、死循环、信号量没有释放等,都有可能导致线程长时间停顿。这是如果能够dump出当前JVM的线程快照,就能够看出没有响应的线程究竟在做什么事情,从而定位问题。
语法:
稍加翻译一下:
-F 用来在输出不被响应时强制生成线程的快照
-m用来答应出包含Java和native代码的所有堆栈信息
-l 打印出锁的附加信息
可以配合jps命令找出pid

71. JAVA中的线程调度算法

抢占式。一个线程用完CPU之后,操作系统会根据现场优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。

72. Thread.sleep(0)有什么作用?

由于Java采用抢占式的线程调度算法,因此可能会出现某条线程尝尝获取到CPU控制权的情况,为了让某些优先级比较低的线程能获取到CPU控制权,可以使用Thread.sleep(0)手动触发一次操作系统分配时间片的操作,这也是平衡CPU控制权的一种操作。

73. CAS

全称CompareAndSwap。假设有三个操作数:内存值V,旧的预期值A,要修改的值B,当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返回true,否则什么都不做并返回false。当然CAS一定要配合volatile变量,这样才能保证每次拿到的遍历是主内存中最新的那个值,否则旧的预期值A对某条线程来说,永远是一个不会变的值A,只要某次CAS操作失败,永远都不可能成功。

74. AQS

全称AbstractQueuedSynchronizer。如果说JUC(java.util.concurrent)的基础是CAS的话,那么AQS就是整个JAVA并发包的核心了,ReentrantLock, ReentrantReadWriteLock, CountDownLatch, Semaphore等都用到了它。

75.合理地配置线程池

需要针对具体情况而具体处理,不同的任务类别应采用不同规模的线程池,任务类别可划分为CPU密集型任务、IO密集型任务和混合型任务。
- 对于CPU密集型任务:线程池中线程个数应尽量少,不应大于CPU核心数;
- 对于IO密集型任务:由于IO操作速度远低于CPU速度,那么在运行这类任务时,CPU绝大多数时间处于空闲状态,那么线程池可以配置尽量多些的线程,以提高CPU利用率;
- 对于混合型任务:可以拆分为CPU密集型任务和IO密集型任务,当这两类任务执行时间相差无几时,通过拆分再执行的吞吐率高于串行执行的吞吐率,但若这两类任务执行时间有数据级的差距,那么没有拆分的意义。

76. happens-before原则

  1. 程序次序规则(Pragram Order Rule):在一个线程内,按照程序代码顺序,书写在前面的操作先行发生于书写在后面的操作。准确地说应该是控制流顺序而不是程序代码顺序,因为要考虑分支、循环结构。
  2. 管程锁定规则(Monitor Lock Rule):一个unlock操作先行发生于后面对同一个锁的lock操作。这里必须强调的是同一个锁,而”后面“是指时间上的先后顺序。
  3. volatile变量规则(Volatile Variable Rule):对一个volatile变量的写操作先行发生于后面对这个变量的读取操作,这里的”后面“同样指时间上的先后顺序。
  4. 线程启动规则(Thread Start Rule):Thread对象的start()方法先行发生于此线程的每一个动作。
  5. 线程终于规则(Thread Termination Rule):线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过Thread.join()方法结束,Thread.isAlive()的返回值等作段检测到线程已经终止执行。
  6. 线程中断规则(Thread Interruption Rule):对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测是否有中断发生。
  7. 对象终结规则(Finalizer Rule):一个对象初始化完成(构造方法执行完成)先行发生于它的finalize()方法的开始。
  8. 传递性(Transitivity):如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论。

77. 多线程三大定律

  1. Amdahl 定律
    –Gene Amdahl 发现在计算机体系架构设计过程中,某个部件的优化对整个架构的优化和改善是有上限的。这个发现后来成为知名的Amdahl 定律。
    比如:即使你有10个老婆,也不能一个月把孩子生下来。
  2. Gustafson 定律
    –Gustafson假设随着处理器个数的增加,并行与串行的计算总量也是可以增加的。Gustafson定律认为加速系数几乎跟处理器个数成正比,如果现实情况符合Gustafson定律的假设前提的话,那么软件的性能将可以随着处理个数的增加而增加。
    比如:当你有10个老婆,就会要生更多的孩子。
  3. Sun-Ni 定律
    –充分利用存储空间等计算资源,尽量增大问题规模以产生更好/更精确的解。
    比如:你要设法让每个老婆都在干活,别让她们闲着。

持续更新中~
博主呕心沥血整理发布,跪求一赞。

参考资料
1. 《Java多线程编程核心技术》高洪岩著。
2. 《Java并发编程的艺术》方腾飞 等著。
3. 《Java并发编程实战》Brian Goetz等著。
4. 深入JDK源码之ThreadLocal类
5. JAVA多线程之扩展ThreadPoolExecutor
6. Comparable与Comparator浅析
7. JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止
8. JAVA线程间协作:Condition
9. JAVA线程间协作:wait.notify.notifyAll
10. Java中的锁
11. Java守护线程概述
12. Java SimpleDateFormat的线程安全性问题
13. JAVA虚拟机关闭钩子(Shutdown Hook)
14. 40个Java多线程问题总结
15. Java线程池分析

你可能感兴趣的:(java,多线程)