多線程與進程
進程是操作系統中運行的一個任務(一個應用程序運行
在一個進程中)
進程中所包含的一個或多個執行單位稱為線程(thread)
多線程
多線程允許我們可以"同時"執行多段代碼
實際上多線程是並發運行的,即:JVM中的線程調度會為多個
線程分配"CPU時間片",並將這些時間片盡可能均勻的分配
給線程,當一個線程獲取時間片後,該線程熱任務代碼被
CPU執行,其他線程處於等待狀態,這種宏觀上同時運行而微觀
上走走停停的現象被稱為並發.
java中的線程是由Thread的實例表示.
而Thread的創建有兩種方式:
1:繼承Thread並重寫run方法
2:實現Runnable接口並重寫run方法來單獨定義任務
start方法的做作業是將線程納入線程調度.一旦start方法
執行完畢後,那麽該線程的run方法會很快被運行(只要獲
取了CPU時間片)
線程同步是並發運行代碼,兩段代碼間不存在先後運行的概念.
有先後順序運行多段代碼稱為:同步執行
多線程在運行多段代碼時是:異步運行(各自執行各自的)
第一種創建線程的方式雖然定義簡單,但也存在一些不足:
1:由於java是單繼承的,這經常導致在實際開發中,為了
復用一個類的方法,我們需要繼承那個類,而自身又希望
是一個線程時導致的繼承沖突
2:繼承了線程需要重寫run方法來定義該線程執行的任務代碼,
這就導致了線程與執行的任務有一個必然的耦合關系,不利於
線程優先級
對於線程調度的工作,線程不能幹涉,即:線程只能被動
的等待分配CPU時間片,而不能主動獲取.
可以通過修改線程優先級來最大程度改善獲取CPU時間片
的幾率, 理論上, 線程優先級越高的線程獲取CPU時間片
的次數越多.
線程的優先級有10個等級,分別用整數1-10表示.
其中1位最低,10最高,5位默認值
守護線程 守護線程也被稱為後臺線程
默認創建出來的線程都是前臺線程,若要設置為後臺線程
可以通過線程提供的方法setDaemon來完成
後天線程使用上與前臺線程一樣,但是在結束時機上有
一點是不同的,即:當一個進程結束時,所有正在運行的
後臺線程都會強制結束.而進程的結束時當一個進程中
所以將來開發中可以將一直保持運行的任務,但是可以隨著
程序一同結束的放在後臺線程上運行
進入阻塞狀態,直到download執行完畢才會解除阻塞繼續
執行後續代碼
局部變量時,該方法必須是final的
JDK1.8之後由於內存問題被重新定義,不在有這個問題,
所以就不再需要上述設定.
有效的縮小同步範圍可以在保證並發安全的前提下
提高並發的效率
同步塊可以更精確的控制需要同步執行的代碼片段.
有效縮小同步範圍提高並發效率但是需要註意,
同步塊需要指定"同步監視器"即:上鎖的對象,要
保證需要同步運行該代碼的線程看到的該對象是同一個.
多線程並發安全問題
當多個線程並發訪問統一資源時,由於線程切換時機不確定
導致代碼未按照設計方式的順序執行導致的邏輯混亂.嚴重
時可能導致系統癱瘓.
解決多線程並發安全的手段是將"各幹各的"變為"排隊執行"
當一個方法被synchronized修飾後,那麽該方法稱為"同步
方法",即:多個線程不能同時進入到方法內部執行
在方法上使用synchronized修飾後,上鎖的對象就是當
前方法所屬對象,即:方法中看到的this
靜態方法使用synchronized,那麽一點具有同步效果
靜態方法上鎖的對象是該方法所屬類的類對象
實際上JVM在加載一個類的class文件時,會實例化一個Class
類型的實例去保存該類的信息(屬性,方法等).所以JVM
中每個加載過的類都有且只有一個Class的實例用於表示它
這個Class的實例就是該類的類對象
線程安全的集合也不與叠代器遍歷集合的操作 互斥,但是
叠代器要求遍歷的過程中不能通過集合的方法增刪元素,
否則會拋出異常,所以在多個線程間有這樣的操作時,
需要自行維護遍歷 集合與集合元素操作間的互斥關系.
1:控制線程數量.因為線程數多了,會導致內存開銷大.
嚴重時會導致系統癱瘓,並且由於線程數量多會導致
CPU過度切換,拖慢系統響應.
2:重用線程
多線程與進程