Java多线程知识小抄集(四)——完结
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。
歡迎跳轉到本文的原文鏈接:https://honeypps.com/java/java-multiple-thread-summary-4/
本文主要整理博主遇到的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. 多線程三大定律
–Gene Amdahl 發現在計算機體系架構設計過程中,某個部件的優化對整個架構的優化和改善是有上限的。這個發現后來成為知名的Amdahl 定律。
比如:即使你有10個老婆,也不能一個月把孩子生下來。
–Gustafson假設隨著處理器個數的增加,并行與串行的計算總量也是可以增加的。Gustafson定律認為加速系數幾乎跟處理器個數成正比,如果現實情況符合Gustafson定律的假設前提的話,那么軟件的性能將可以隨著處理個數的增加而增加。
比如:當你有10個老婆,就會要生更多的孩子。
–充分利用存儲空間等計算資源,盡量增大問題規模以產生更好/更精確的解。
比如:你要設法讓每個老婆都在干活,別讓她們閑著。
77. 進程間通信方式
- 管道( pipe ):管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。
- 有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。
- 信號量( semophore ) : 信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
- 消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中并由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。
- 信號 ( sinal ) : 信號是一種比較復雜的通信方式,用于通知接收進程某個事件已經發生。
- 共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號兩,配合使用,來實現進程間的同步和通信。
- 套接字( socket ) : 套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同及其間的進程通信。
持續更新中~
博主嘔心瀝血整理發布,跪求一贊。
參考資料
歡迎跳轉到本文的原文鏈接:https://honeypps.com/java/java-multiple-thread-summary-4/
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。
總結
以上是生活随笔為你收集整理的Java多线程知识小抄集(四)——完结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java虚拟机结构分析
- 下一篇: (RabbitMQ) Java Clie