寫在開頭
ok,everybody,在過去的兩週內,我們大體上講完了Java的集合,在最後我們探討了關於HashMap執行緒不安全的原因,又提出了ConcurrentHashMap這個執行緒安全的集合解決方案,那麼在接下來的2-3周內,我們就一起來學習一下Java中的併發多執行緒。
在開始學習之前,我們必須要搞清楚幾個概念:執行緒與程序、併發與並行、同步與非同步。
執行緒與程序
Java的併發指的是多執行緒,而與多執行緒對應的有個程序的概念,啥是程序呢?我們透過CTRL+SHIFT+ESC
組合快捷鍵開啟電腦的工作管理員,我們就看到了如下的這幅圖。
這裡面執行的每一條就是一個程序,它是程式執行時的一個例項,作業系統會為每個程序分配獨立的記憶體地址空間,因此,程序也是系統進行資源分配和排程的基本單位。
而執行緒是比程序更小的執行單位,是程序的子任務,因此它本身不會獨立存在,系統不會為執行緒分配記憶體,執行緒組之間只能共享所屬程序的資源,而執行緒僅僅是CPU 排程和分派的基本單位,當前執行緒 CPU 時間片用完後,會讓出 CPU 等下次輪到自己時候在執行。
程序與執行緒的關係
-
一個程式至少一個程序,一個程序至少一個執行緒,程序中的多個執行緒是共享程序的資源(堆,字串常量池(JDK1.8)/方法區(JDK1.7));
-
一個程序中有多個執行緒,多個執行緒共享程序的堆和方法區資源,但是每個執行緒有自己的程式計數器,棧區域;
-
Java 中當我們啟動 main 函式時候就啟動了一個 JVM 的程序,而 main 函式所線上程就是這個程序中的一個執行緒,也叫做主執行緒。 我們透過JMX(Java Management Extensions)管理器去監控一下JVM,看下面這段程式碼示例:
【程式碼示例1】
public class Test {
public static void main(String[] args) {
// 獲取 Java 執行緒管理 MXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// 不需要獲取同步的 monitor 和 synchronizer 資訊,僅獲取執行緒和執行緒堆疊資訊
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
// 遍歷執行緒資訊,僅列印執行緒 ID 和執行緒名稱資訊
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName());
}
}
}
輸出:
[6] Monitor Ctrl-Break //監控Ctrl-Break中斷訊號的執行緒
[5] Attach Listener //新增事件
[4] Signal Dispatcher // 分發處理給 JVM 訊號的執行緒
[3] Finalizer //呼叫物件 finalize 方法的執行緒
[2] Reference Handler //清除 reference 執行緒
[1] main //main 執行緒,程式入口
由此可見一個JVM程序在執行時,包含了很多個子執行緒。
併發與並行
並行: 指兩個或兩個以上事件或活動在同一時刻發生。如多個任務在多個 CPU 或 CPU 的多個核上同時執行,不存在 CPU 資源的競爭、等待行為。
併發: 併發指在某時刻只有一個事件在發生,某個時間段內由於 CPU 交替執行,可以發生多個事件,存在對 CPU 資源進行搶佔。
同步與非同步
同步: 發出一個呼叫之後,在沒有得到結果之前, 該呼叫就不可以返回,一直等待。
非同步: 呼叫在發出之後,不用等待返回結果,該呼叫直接返回。
結尾彩蛋
如果本篇部落格對您有一定的幫助,大家記得留言+點贊+收藏呀。原創不易,轉載請聯絡Build哥!
如果您想與Build哥的關係更近一步,還可以關注俺滴公眾號“JavaBuild888”,在這裡除了看到《Java成長計劃》系列博文,還有提升工作效率的小筆記、讀書心得、大廠面經、人生感悟等等,歡迎您的加入!