Java進階---并發編程

一.線程復習

1.什么是線程,進程

進程是操作系統分配資源的基本單位

線程是進程中的一個執行單元(一個獨立執行的任務),是cpu執行的最小單元

2.Java中如何創建線程

1.繼承Thread類,重寫run(),直接創建子類的對象

2.類實現Runnable接口,重寫run(),? 任務類? ?new Thread(任務類對象)

3.類實現Callable接口

4.線程池

3.線程中常用的方法

run()? ?call()

Thread類中的方法:

? ? ? ? start();啟動線程的,把線程注冊到操作系統private native void start0();

? ? ? ? sleep();讓線程休眠指定的時間

? ? ? ? join();讓其他線程等待當前線程執行完成后再執行

? ? ? ? yeild();線程禮讓

? ? ? ? setDaemon();設置線程為守護線程

? ? ? ? currentThread();獲得當前正在執行的線程

? ? ? ? wait();讓線程等待,只能被其他線程喚醒

? ? ? ? notify();notifyAll();喚醒被wait等待的線程

4.線程的狀態

5.多線程

(1)什么是多線程

在程序中(進程)可以創建多個線程來分別執行不同的任務

(2)多線程優缺點

優點:可以提高程序執行效率

缺點:線程多了,需要操作系統進行管理的,占用開銷的(不是啥事情都創建線程執行的.)

? ? ? ? ? ?多個線程同時訪問共享資源(數據)會出現問題

(3)線程同步

加鎖排隊 (飯堂買飯 排隊+加鎖 一次只能有一個買飯)

synchronized關鍵字:

? ?synchronized修飾方法 非靜態方法鎖對象是this 靜態方法是類的Class對象

? ?synchronized修飾代碼塊

ReentrantLock

public class ReentrantLockDemo  implements  Runnable{int num = 10;/*ReentrantLock是java.util.concurrent.locks包下的類,是java代碼實現的一種鎖控制只能手動的加鎖和手動的釋放鎖只能對某段代碼塊加鎖,不能給整個方法加法*/ReentrantLock reentrantLock = new ReentrantLock();@Overridepublic void run() {while (true){try { reentrantLock.lock();//加鎖   if (num > 0) {System.out.println(Thread.currentThread().getName() + "買到第" + num + "張票");num--;} else {break;}}finally {reentrantLock.unlock();//釋放鎖}}}
}
(4)死鎖

多個線程相互持有對方需要的鎖對象不釋放,二形成的一種相互等待獲取鎖的現象,

死鎖發生后,程序不會報錯,只能相互等待,不繼續向后執行了.

如何避免死鎖發生:

????????避免鎖的嵌套使用

????????避免多個同步代碼塊中的鎖相互使用

口語描述死鎖:

???????線上1和線程2 同時訪問兩個代碼塊, 線程1訪問的同步代碼塊使用A鎖,在A鎖的同步代碼塊又使

用了B鎖. ?

????????線程2在訪問的同步代碼塊中使用B鎖,在B鎖的同步代碼塊中又用到了A鎖,有可能形成死鎖.

(5)線程通信(生產者,消費者模型)

在線程同步的基礎上進行的,兩個線程相互牽制執行

wait(); 線程等待

notify(); 喚醒等待的線程

只能在同步代碼塊(同步方法)中使用, 還只能通過同步鎖對象調用

案例:交替打印數字

public class PrintNum  implements  Runnable{int num = 0;Object obj = new Object();@Overridepublic void run() {while (true){synchronized(obj){obj.notify();System.out.println(Thread.currentThread().getName()+":"+num++);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}try {obj.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}}}
}

wait()和sleep()區別:

????????所屬的類不同: wait()屬于Object類 sleep()屬于Thread類

????????阻塞后喚醒方式不同: wait()讓線程等待后,需要讓另一個線程通過notify()喚醒,如果不喚醒一直

等待

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sleep()休眠執定的時間,時間到了后,自動喚醒

? ? ? ? 釋放鎖不同: sleep()不會釋放鎖

? ? ? ? ? ? ? ? ? ? ? ? ? ? wait()會釋放鎖

二.線程進階---并發編程

后面談論的線程內容,幾乎都是在多線程對同一共享數據操作的基礎上進行.

1.多線程優缺點

優點: 可以提高程序執行效率

缺點: 線程多了,需要操作系統進行管理的,占用開銷的(不是啥事情都創建線程執行的.)

? ? ? ? ?多個線程同時訪問共享資源(數據)會出現問題

并發(高并發): 計算機領域指的是同一時刻只能有一個任務執行,多個任務依次執行

? ? ? ? ? ? ? ? ? ? ? ?漢語并發指的是同時執行

并發執行: 在很多用戶同時訪問時,應當讓多個用戶并發執行(一個時間段內依次執行)

并行執行: 在同一個時間點上,多個任務同時執行

2.并發編程核心問題

????????多個線程同時對同一個資源訪問的情況下. 為什么會出現問題.

(1)不可見性

????????首先了解java程序運行的內存模型(JMM)

? ? ? ? java在線程操作時,先把主內存中的數據加載到線程的工作內存中,然后對數據進行操作, 但是

線程A在自己的工作內存中操作玩出,線程B不知道,做了同樣的操作,最終結果和預期結果不一樣

(2)亂序性(無序性)重排序

系統為了優化,在執行某些指令時,會將一些看起來沒關系的指令執行順序改變,但是在,某些情況下會

產生問題.

1? ? int a = 10;

2 ? ?int ?b = ?從數據庫讀取

3? ? int c = a+b;

(3)非原子性

i++;在多線程情況下時線程安全的嗎?

i++高級語言,在底層執行時,會被分為3條件

加載i

i+1

i=2

線程的切換執行會帶來原子性問題

java內存模型為每個線程提供工作內存(緩存),導致不可見性問題

系統指令優化會把一些指令順序重排序(在執行一些較為耗時的指令時,把一些其他指令先行執行),

可能導致程序無法正常執行

線程切換執行會打破指令執行的原子性 ,例如++操作 分為三條指令, 但是在執行這3條指令時,cpu可

能在執行時,切換到其他線程執行,打破原子性執行.

(4)如何解決以上3個問題:

volatile

volatile關鍵可以解決不可見性和亂序性

**volatile**修飾的共享變量,在被一個線程操作后,可以做到立即對其他線程可見 (volatile底層

實現內存屏障)

volatile修飾的變量禁止對其的執行順序重排序

volatile只能解決不可見性和重排序問題, 不能解決非原子性問題

(5)如何解決非原子性問題:

? ? ? ? 1.加鎖(ReentrantLock和synchronized)

? ? ? ? 2.使用原子類來解決++在多線程中非原子性問題

AtomicInteger 是一個原子類,能夠在不加鎖的情況下,實現多線程++操作不出問題,結果正確

private  static AtomicInteger atomicInteger = new AtomicInteger(0);atomicInteger.incrementAndGet();  自增并獲得

CAS 機制

CAS(Compare-And-Swap) :比較并交換

特點: 不加鎖實現對變量++操作保證原子性.

優點: 線程不會進入到阻塞狀態,一直自旋,效率高

缺點: 線程一直自旋,對cpu開銷大, 所以原子類適用于線程少的情況

3.Java中的鎖分類

(1)樂觀鎖/悲觀鎖

樂觀鎖: 就是沒有加鎖的實現. AtomicInteger中的實現就是不加鎖的,通過自旋比較實現(CAS)

悲觀鎖: 就是加鎖的實現,認為不加鎖是會出問題的 ,ReentrantLock和synchronized都是悲觀鎖

(2)可重入鎖

ReentrantLock和synchronized都是可重入鎖

可重入鎖又名遞歸鎖, 指的是一個線程在外層方法獲得鎖時,可以直接進入到內層的加鎖的方法中.

(3)自旋鎖

指的是對synchronized獲得鎖的一種描述(特點), 線程在獲得鎖時,是自旋的不斷嘗試去獲得鎖

(4)公平鎖/非公平鎖

公平鎖: 就是排隊獲得鎖,有先來后到 ReentrantLock 既可以是公平鎖也可以是非公平鎖

非公平鎖: 就是搶鎖,誰搶到誰執行, 有可能后來的線程先搶到鎖 synchronized ReentrantLock

(5)讀寫鎖

ReentrantReadWriteLock

特點: 讀讀不互斥, 讀寫互斥, 寫寫互斥

適合讀(查詢)多,寫少的場景, 提高讀的效率

(6)共享鎖和獨占鎖

獨占鎖: synchronized ReentrantLock都是獨占鎖,就是有我沒他,一次只能有一個線程執行.

共享鎖: 一個鎖可以被多個線程持有, 讀寫鎖中的讀鎖就是共享鎖

4.synchronized鎖的實現

jdk1.7之后,對synchronized鎖進行了優化(jdk7之前synchronized鎖沒有狀態,都是自旋的獲取鎖),

jdk7之后為synchronized鎖設計了不同的狀態.

無鎖狀態: 沒有線程進入到同步代碼塊就是無鎖狀態

偏向鎖狀態: 只有一個線程訪問同步代碼塊時,同步鎖中記錄線程id,下次線程訪問時,可以快速的獲

得鎖.

輕量級鎖狀態: 當線程數量大于1個之后,鎖狀態由偏向鎖升級為輕量級鎖, 線程不會阻塞,以自旋方

式獲得鎖,提高獲取鎖的效率.

重量級鎖狀態: 當鎖狀態為輕量鎖時,如果線程自旋到一定次數還獲取不到鎖,那么鎖會升級為重量級

鎖,讓獲取不到鎖的線程進入到阻塞狀態,等待操作系統調度.

使用synchronized鎖的時候,必須為鎖提供一個同步鎖對象的,此對象就是用來記錄鎖狀態的

對象中有一個區域叫對象頭,對象頭中中有一塊區域叫mark word,記錄對象運行時的一些數據,

如鎖狀態,哈希值,GC分代年齡,當前線程id.

synchronized時java中內置的一種的鎖,底層實現是靠底層指令進行控制的,

使用時必須提供一個同步鎖對象,用來記錄鎖的各種狀態.

5.AQS

AbstractQueuedSynchronizer 抽象同步隊列, 并發包下面很多類的底層實現都會用到

內部有一個int類的變量state,用來記錄有沒有線程使用

內部會構建一個隊列,用來存儲沒有獲得鎖的線程

6.ReentrantLock鎖實現

ReentrantLock 基于 AQS的,

ReentrantLock 可以實現公平鎖和非公平鎖

內部結構

公平和非公平的區別

三.Java集合類復習

javaSE中3個重點: 面向對象相關知識

??????????????????????????????集合類 (數據結構,線程)

??????????????????????????????多線程

次重點: 網絡 (計網)

?????????????IO

? ? ? ? ? ? ?常用類

? ? ? ? ? ? ?異常

單列集合 Collection

???????List

????????????????ArrayList 底層數組實現 查詢塊

????????????????LinkedList ? 底層鏈表 ? 查詢慢

????????????????Vector 底層也是數組,是線程安全的

????????Set

????????????????HashSet

????????????????TreeSet

雙列集合 Map

????????HashMap

????????TreeMap

????????Hashtable

1.你能講一下HashMap嗎?

基本特點: 雙列集合,鍵不能重復,值可以重復,可以有一個key為null

數據結構:

源碼

put方法源碼分析

public V put(K key, V value) {//通過key計算哈希值return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {int h;                       為了減少哈希值沖突return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; //哈希表Node<K,V> p; //記錄之前int n, i; //n是哈希表長度, i是索引if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//創建哈希表if ((p = tab[i = (n - 1) & hash]) == null) // == 97%16 根據哈希值計算位置//如果該位置為null,則直接將key,value包裝到一個node對象中,直接存放到第i個位的第一個tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;//判斷key是否重復, 先判斷哈希值(快),但是哈希有問題,值相同,但內容不同,//所以在哈希值相同時,需要調用equals(),判斷內容是否相同.if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//當key不重復時,判斷類型是樹類型還是鏈表類型else if (p instanceof TreeNode)//已經是樹類型,向紅黑樹上添加元素e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {//鏈表for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);//添加完成后,判斷鏈表長度if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);//轉紅黑樹break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;//key相同時,會用后面key的值,覆蓋之前的相同的key的值afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}

重點參數:

1.哈希表長度: 默認是16

2.哈希表每次擴容原來 2 倍

3.哈希表的負載因子 0.75, 哈希表不會裝滿的,裝滿會影響查詢效率,所以會犧牲一定的空間而換取查詢效率

4.鏈表長度上限是 8 ,嘗試將鏈表轉為紅黑樹,但是不一定轉成功, 還會判斷哈希表長度,哈希表長度小于64 會先擴容哈希表,擴容后所有元素位置需要重新計算,這樣鏈表會變短, 只有當鏈表長度大于等于8且哈希表長度大于64,鏈表才會轉成紅黑樹.

5.當紅黑樹節點數量減少為6個時,紅黑樹退化成鏈表

2.ConcurrentHashMap

ConcurrentHashMap是一個線程安全的map,加鎖的方式與Hashtable不同

Hashtable直接在方法上加鎖,一次只能有一個線程進入方法操作.

ConcurrentHashMap不是給方法加的鎖,個每個哈希表中的位置加鎖

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90649.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90649.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90649.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小車循跡功能的實現(第六天)

&#x1f468;?&#x1f4bb;個人主頁&#xff1a;開發者-削好皮的Pineapple! &#x1f468;?&#x1f4bb; hello 歡迎 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;?&#x1f4bb; 本文由 削好皮的Pineapple! 原創 &#x1f468;?&#x1f4…

C++ auto與 for循環

一、數組 #include <iostream> #include <vector> using namespace std; int main() {int vec[6] {1,2,3};for (auto num : vec) { /* num 是 int */ cout << "Hello, world!" << num <<endl;}return 0; }二、STL容器與迭代器 for 循…

【RK3568+PG2L50H開發板實驗例程】FPGA部分 | ROM、RAM、FIFO 的使用

本原創文章由深圳市小眼睛科技有限公司創作&#xff0c;版權歸本公司所有&#xff0c;如需轉載&#xff0c;需授權并注明出處&#xff08;www.meyesemi.com) 1.實驗簡介 實驗目的&#xff1a; 掌握紫光平臺的 RAM、ROM、FIFO IP 的使用 實驗環境&#xff1a; Window11 PDS2022…

力扣-21.合并兩個有序鏈表

題目鏈接 21.合并兩個有序鏈表 class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode p1 list1;ListNode p2 list2;ListNode p new ListNode(0);ListNode cur p;while (p1 ! null && p2 ! null) {if (p1.val > p2.val) …

MoE混合專家模型:千億參數的高效推理引擎與架構革命

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; 從稀疏激活到多模態協同的智能計算范式 &#x1f9e9; 一、核心思想與…

【論文筆記】BlockGaussian:巧妙解決大規模場景重建中的偽影問題

論文地址&#xff1a;https://arxiv.org/pdf/2504.09048 大規模場景的重建方法不僅僅對于高空航拍數據有效&#xff0c;而且對于地面大中場景也有增強效果&#xff0c;故專門來學習一下這一方向的知識。感謝作者大佬們的great work。 Abstract 三維高斯潑濺&#xff08;3DGS…

網絡眾籌項目數據庫(2014-2024.11)

1727網絡眾籌項目數據庫&#xff08;2014-2024.11&#xff09;數據簡介作為新興互聯網融資模式&#xff0c;眾籌已成為越來越多創業者和中小企業獲取資金的渠道&#xff0c;但眾籌項目一直面臨融資成功率低的困難&#xff0c;成功融資的項目在許多平臺上占比不足五成。而目前對…

k8s新增jupyter服務

k8s新增服務 常用命令 kubectl apply -f xxxxxx.yaml # 部署資源&#xff0c;順序&#xff1a;namespace -> pvc -> deployment -> servicekubectl create namespace jupyter # 創建namespacekubectl get namespaces # 查看nskubectl get pods -n jupyter # 查看p…

結構化數據、非結構化數據區別

一、核心定義結構化數據&#xff1a;指具有固定格式、可直接用二維表&#xff08;如數據庫表&#xff09;表示的數據&#xff0c;其字段&#xff08;列&#xff09;定義明確&#xff0c;數據之間的關系清晰。例如&#xff1a;Excel 表格中的數據、關系型數據庫&#xff08;MySQ…

Linux修煉:基礎指令

Hello大家好&#xff01;很高興我們又見面啦&#xff01;給生活添點passion&#xff0c;開始今天的編程之路&#xff01; 我的博客&#xff1a;<但凡. 我的專欄&#xff1a;《編程之路》、《數據結構與算法之美》、《題海拾貝》、《C修煉之路》、《Linux修煉&#xff1a;終端…

【Linux網絡】深入理解HTTP/HTTPS協議:原理、實現與加密機制全面解析

協議是通信雙方必須遵守的規則&#xff0c;確保數據能夠正確傳輸和解析&#xff0c;它規定了數據格式、傳輸順序、錯誤處理等細節。應用層的協議一般都是我們自己進行定義的&#xff0c;但是有很多程序員前輩已經寫出來了很哇塞的協議&#xff0c;我們直接進行學習和使用即可HT…

淺嘗 Spring AI【使用超級簡單~】

一直想要體驗下 Spring AI&#xff0c;最近自己的一個工具有這個需求&#xff0c;所以這里準備使用下。其實使用起來超級簡單。 1.IDEA 新建 Spring項目 1&#xff09;這里可以根據自己的喜好選擇 項目名、jdk版本等 2&#xff09;這里選擇 在ai中選擇 openAI 即可。然后我另…

DDL期間TDSQL異常會話查詢造成數據庫主備切換

問題描述&#xff1a;7*24聯機交易系統&#xff0c;傍晚時分&#xff0c;從客戶端后臺對3千萬行的大表執行縮短varchar類型字段長度的ddl語句&#xff0c;執行期間&#xff0c;為了查看ddl進度&#xff0c;從TDSQL-MySQL赤兔前端頁面點擊異常會話查詢&#xff0c;之后數據庫卡住…

弧焊機器人氣體全方位節能指南

氬弧焊&#xff08;TIG焊接&#xff09;作為其中一種高效且精密的技術&#xff0c;憑借其穩定性和高質量的焊接效果&#xff0c;在航空航天、汽車制造、船舶建造以及石油化工等領域占據了不可或缺的地位。氬弧焊通過使用惰性氣體&#xff08;如氬氣&#xff09;保護電弧和熔池&…

數據清洗(ETL/ELT)原理與工具選擇指南:企業數字化轉型的核心引擎?

目錄 一、數據清洗&#xff08;ETL/ELT&#xff09;到底在干啥&#xff1f; 1.揪出并處理異常值 2.把缺失的數據補上&#xff08;或處理好&#xff09; 3.數據轉換與標準化 4.一致性校驗 二、工具怎么選&#xff1f;看菜吃飯&#xff0c;量體裁衣 1.數據量不大、要求不高…

阿里云服務器,CentOS7.9上安裝YApi 接口管理平臺

目錄 1.node安裝 1.1下載node,解壓 1.2 部署bin文件 1.3 安裝mongodb 2.啟動yapi 2.1 前置命令 2.2 啟動服務 3.利用pm2方便服務管理維護 3.1.安裝pm2 3.2 常用 PM2 命令 4.常見問題 4.1. 確認 MongoDB 是否安裝 4.2. 安裝 MongoDB&#xff08;若未安裝&#xff…

阿里云錯題集分享

有最近想要考試阿里云的可以私信我 &#xff0c;一起加油錯題集1.在使用阿里云的負載均衡SLB實例時&#xff0c;做了如下健康檢查的配置:成功響應和超時響應時間均為1秒&#xff0c;健康檢查間隔為2秒&#xff0c;不健康閾值為3&#xff0c;健康閾值為3。即對于確認一個云服務器…

Android 12 - 部分相機橫屏顯示方案

1.相機過渡界面方向旋轉 Android 10 - 相機過渡界面默認角度 同A10 有些區別&#xff0c;再次增加記錄修改。 這個文件沒有修改&#xff0c;只是說明 src/com/android/camera/CameraActivity.javaprivate void freezeScreenCommon(boolean async) {long startTime System.…

Operation Blackout 2025 Phantom Check hayabusa+ControlSet001+VirtualBox

QAQA攻擊者使用哪個 WMI 類來檢索型號和制造商信息以進行虛擬化檢測&#xff1f;Win32_ComputerSystem攻擊者執行了哪個 WMI 查詢來檢索計算機的當前溫度值&#xff1f;SELECT CurrentTemperature FROM MSAcpi_ThermalZoneTemperature攻擊者加載了 PowerShell 腳本以檢測虛擬化…

《O-PAS?標準的安全方法》白皮書:為工業自動化系統筑起安全防線

The Open Group 最新白皮書《O-PAS?標準的安全方法》重磅發布&#xff0c;為流程工業在邁向開放架構與多供應商互操作的過程中&#xff0c;指明了安全實踐的方向。O-PAS?標準的安全方法ABOUT PUBLICATION亮點一&#xff1a;首次系統闡釋 O-PAS? 標準安全方法與 IEC/ISA 6244…