Java高併發編程詳解學習筆記(一)

前言:要秋招了,複習一下應對秋招,糾結該先看啥,最後決定先學習《Java高併發編程詳解》,此博客爲看書所寫的筆記,因爲是筆記,所以會只記比較重要的東西,不適合初學者

參考:

https://blog.csdn.net/q610376681/article/details/87922812

目錄

第一章 快速認識線程

1.1 線程的生命週期

1.2 模板設計模式在Thread中的應用

1.3 策略模式在Thread中的使用

第二章 深入理解Thread構造函數

2.1 線程的命名

2.2 線程的父子關係

2.3 Thread與ThreadGroup

2.4 Thread與JVM虛擬機棧

2.4.1 JVM內存結構

2.4.2 Thread與虛擬機棧的關係

2.5 守護線程


第一章 快速認識線程

當JVM啓動時啓動了一個進程,如果在進程中增加線程呢?用Thread.start即可,Thread類的對象在沒調用start方法時僅僅是一個對象,調用了才能啓動一個線程。

JVM啓動時創建的不知有main線程,還有一些垃圾回收線程,RMI線程等等。

1.1 線程的生命週期

NEW是Thread對象還沒調用start方法時的狀態

Runnable是調用Start方法但是還沒獲取到CPU的調度資格,處於此狀態下的線程只能意外終止或者進入Running狀態

Running狀態是獲取到CPU正在運行的線程,可以通過stop直接進入Terminated狀態,也可能因爲調用sleep,wait,調用了某個阻塞的IO,需要獲取某個鎖資源而進入Blocked狀態,或者是因爲cpu輪轉或者yield放棄cpu而進入Runnable狀態。

Blocked狀態是線程進入了阻塞狀態,可以直接進入Terminated狀態,可以因休眠結束、被喚醒、獲取到了鎖資源、阻塞過程中被打斷而進入Runnable狀態。

Terminated是線程的最終形態,該狀態下不會切換到任何狀態

注:一個Thread只能start一次

1.2 模板設計模式在Thread中的應用

我們都知道最終start會調用run方法來新開線程,這其實是典型的模板模式,父類編寫算法結構代碼,子類實現邏輯細節。

在這裏父類開啓線程,子類重寫run方法實現具體細節。

模板模式介紹:https://www.jianshu.com/p/800a44c1d9dd

1.3 策略模式在Thread中的使用

當我們模擬一個多線程叫號程序時,當前的號碼是共享資源,可以通過將共享變量置爲static來解決,但是如果共享資源很多且要經過比較複雜的計算呢?不可能都用static修飾,Java提供了一個接口Runnable專門解決該問題,將線程的控制和業務邏輯的運行分離開來。

TicketWindow extend Threads {
    private static int index = 1;
}

 我們新建類實現接口,將具體的業務邏輯在接口中完成,然後新建thread時將接口實現類傳入,它便會調用我們接口實現的方法,完成相應的業務邏輯。

策略模式講解:https://baijiahao.baidu.com/s?id=1638224488060180625&wfr=spider&for=pc

 

第二章 深入理解Thread構造函數

2.1 線程的命名

線程默認以Thread-作爲前綴與一個自增數字進行組合,也可在新建的時候進行命名,線程啓動之前可以修改名字,啓動後名字不能修改。

2.2 線程的父子關係

任何創建的線程都會有一個父線程,一個線程的創建肯定是由另一個線程完成的,被創建線程的父線程是創建它的線程。

2.3 Thread與ThreadGroup

Thread的構造函數中,可以顯式地指定線程的group,如果不指定,則子線程會加入父線程所在的線程組,main線程所在的ThreadGroup稱爲main

2.4 Thread與JVM虛擬機棧

Thread的構造函數中,有一個特殊的參數stackSize。

一般情況下,創建線程的時候不會手動指定棧內存的地址空間字節數組,統一通過xss參數進行設置即可,stacksize越大表示線程內方法調用遞歸的深度就越深,stacksize越小則代表創建的線程數據量越多。

2.4.1 JVM內存結構

程序計數器:無論任何語言都需要由操作系統通過控制總線向CPU發送機器指令,程序計數器在JVM中所起的作用就是用於存放當前線程接下來將要執行的字節碼指令、分支、循環、跳轉、異常處理等信息,任何時候,一個處理器只執行其中一個線程中的指令,爲了能夠在CPU時間片輪轉切換上下文之後順利回到正確的執行位置,每條線程都需要具有獨立的程序計數器。

Java虛擬機棧:這也是線程私有的,用於存放局部變量表、操作棧、動態鏈接、方法出口等信息,每個棧幀存放對應時刻的以上信息,方法的調用對應着棧幀的出棧和入棧。

本地方法棧:Java中提供了調用本地方法的接口,也就是C/C++程序,一些網絡通信,文件操作的底層便需要調用本地方法,JVM爲本地方法所劃分的內存區域便是本地方法棧。

堆內存:堆內存是JVM中最大的一塊內存區域,被所有的線程所共享,Java在運行期間創建的所有對象幾乎都存放在該內存區域,因此該區域也是垃圾回收器重點照顧的區域,因此有些時候堆內存被稱爲“GC堆”,堆內存一般被分爲新生代和老年代,更細緻的分爲Eden區、From Survivor區和To Survivor區。

方法區:方法區也是多個線程所共享的內存區域,它主要用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器(JIT)編譯後的代碼等數據,雖然在Java虛擬機規範中,將方法區分爲堆內存的一個邏輯分區,但是它還是經常被成爲非堆,有時也被稱爲持久代。

Java 8元空間:上面介紹了JVM的內存劃分,在JDK1.8之前內存大概都是這樣劃分的,但是自從JDK1.8起,JVM的內存區域發生了一些改變,實際上是持久代被徹底刪除,取而代之的是元空間。

2.4.2 Thread與虛擬機棧的關係

可以粗略的認爲 Java進程內存=堆內存+棧內存*線程個數

當虛擬機棧越大,其它不變,可創建的線程數量就越小;當堆內存越大,可創建的線程數量也會越小,但影響不明顯

一個粗略估算最大線程數量的方法

線程數量=((最大地址空間)-JVM堆內存-系統保留內存)/ThreadStackSize

2.5 守護線程

當JVM中沒有個一個非守護線程,既JVM中全是守護線程時JVM會退出。

如垃圾回收線程是守護線程,當非守護線程main結束後垃圾回收線程會自動結束。

線程可以通過setDaemon設置守護或非守護線程。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章