最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Java 多線程

2023-03-06 12:03 作者:回到唐朝當少爺  | 我要投稿

多線程

  • 進程:程序的基本執(zhí)行實體

  • 線程:操作系統(tǒng)能夠進行運算調(diào)度的最小單位.它被包含在進程之中,是進程中的實際運作單位 簡單理解:應用軟件中相互獨立,可以同時運行的功能

有了多線程,我們就可以讓程序同時做多件事情,提高效率

  • 并發(fā):同一時刻有,多個指令在單個CPU上交替執(zhí)行

  • 并行:在同一時刻,多個指令在多個CPU上同時執(zhí)行

多線程的實現(xiàn)方式

繼承Thread類的方式

  1. 自己定義一個類繼承Thread

  2. 重寫run方法

  3. 創(chuàng)建子類的對象,并啟動線程

實現(xiàn)Runnable接口的方式

  1. 自己定義一個類實現(xiàn)Runnable接口

  2. 重寫里面的run方法

  3. 創(chuàng)建自己的類的對象

  4. 創(chuàng)建一個Thread類的對象并開啟線程

利用Callable接口和Future接口

前兩種方法都沒有返回值,如果想獲取多線程運行的結果:

  1. 創(chuàng)建一個類實現(xiàn)Callable接口

  2. 重寫call(是有返回值的,表示多線程運行的結果)

  3. 創(chuàng)建MyCallable的對象(表示多線程要執(zhí)行的任務)

  4. 創(chuàng)建FutureTask的對象(作用為管理多線程運行的結果)

  5. 創(chuàng)建Thread類的對象,并啟動(表示線程)

三種方式對比

常見的成員方法

細節(jié):

  • 如果我們沒有給線程設置名字,其默認名字為Thread-X(序號從0開始)

  • 如果要給線程設置名字,可以用set方法進行設置,也可以用構造方法

  • 當JVM虛擬機啟動時候,會自動地啟動多條線程,其中有一條線程就叫做main線程,作用就是去調(diào)用main方法,并執(zhí)行里面的代碼.

  • sleep方法哪條線程執(zhí)行到了,哪條線程就會在這里停留對應的時間,時間到了之后就會自動醒來,繼續(xù)執(zhí)行下面的其他代碼

Java采用搶占式調(diào)度的方法,也就是隨機

最小優(yōu)先級為1,最大為10,默認為5,優(yōu)先級越高搶到CPU的概率越高

  • 守護線程: 當其他非守護線程執(zhí)行完畢后,守護線程會陸續(xù)結束 應用場景:如QQ聊天窗口與傳文件,如果聊天窗口關閉了傳文件就沒必要了,所以可以把傳文件設為守護線程

  • yield方法可以讓線程分配盡可能均勻一點,較少使用

  • join方法表示將該線程插到當前線程之前,該線程結束后才會繼續(xù)執(zhí)行當先線程

線程的生命周期

創(chuàng)建線程對象:新建 調(diào)用start()后:有執(zhí)行資格,沒有執(zhí)行權,需要不停地搶CPU:就緒 搶到CPU的執(zhí)行權:執(zhí)行資格,沒有執(zhí)行權:運行(可能又被其他線程搶走CPU的執(zhí)行權回到上一個狀態(tài) run()執(zhí)行完畢:線程死亡,變成垃圾:死亡

sleep()或其他阻塞式方法:沒有執(zhí)行資格沒有執(zhí)行權,等到時間到進入就緒狀態(tài)爭搶CPU

所以:sleep方法睡眠時間到后不會立即執(zhí)行下面的代碼,只有搶到CPU后才能執(zhí)行

線程的安全問題

需求:100張票3個窗口售票

上述代碼運行的結果有問題:

  1. 會出現(xiàn)同一張票賣給多個人

  2. 會出現(xiàn)超出100張票,如101,102

原因:線程執(zhí)行時有隨機性,某個線程執(zhí)行到一半就會被其他線程搶走,加入剛好在ticket++執(zhí)行完被搶走,別的線程執(zhí)行完ticket++再回到原線程時,sout打印的ticket就變了

同步代碼塊

把操作共享數(shù)據(jù)的代碼鎖起來

  • 特點1:鎖默認打開,有一個線程進去了,鎖自動關閉

  • 特點2:里面代碼全部執(zhí)行完畢,線程出來,鎖自動打開

同步方法

就是把synchronized關鍵字加到方法上

格式:

  • 特點1:同步方法是鎖住方法里面所有的代碼

  • 特點2:鎖對象不能自己制定

    • 非靜態(tài):this

    • 靜態(tài):當前類的字節(jié)碼文件對象

StringBuilder與StringBuffer:后者每個方法都加了synchronized,是線程安全的

Lock鎖

雖然我們可以理解同步代碼塊和同步方法的鎖對象問題,但是我們并沒有直接看到在哪里加上了鎖,在哪里釋放了鎖,為了更清晰地表達如何枷鎖和釋放鎖,JDK5以后提供了一個新的鎖對象Lock

Lock實現(xiàn)提供比使用synchronized方法和語句可以獲得更廣泛的鎖定操作 Lock中提供了獲得鎖和釋放鎖的方法 void lock()獲得鎖 void unlock()釋放鎖

Lock是接口不能直接實例化,這里采用它的實現(xiàn)類ReentrantLock來實例化 ReentrantLock的構造方法 ReentrantLock()創(chuàng)建一個ReentrantLock的實例

上述代碼有問題,在19:break;行,假設線程1拿到了CPU的執(zhí)行權,此時線程1調(diào)出了循環(huán),沒有執(zhí)行22:lock.unlock();,此時程序不會結束,鎖沒有關上

正確寫法:使用try{}catch(){}finally{}

死鎖

死鎖是一個錯誤,我們應該避免發(fā)生

千萬不要讓兩個鎖嵌套起來

生產(chǎn)者和消費者(等待喚醒機制)

生產(chǎn)者和消費者是一個十分經(jīng)典的多線程協(xié)作的模式

生產(chǎn)者:生產(chǎn)數(shù)據(jù) 消費者:消費數(shù)據(jù)

常見方法:

阻塞隊列

繼承結構

接口:Iterable,Collection,Queue,BlockingQueue 實現(xiàn)類:

  • ArrayBlockingQueue(底層是數(shù)組,有界)

  • LinkedBlockingQueue(底層是鏈表,無界但不是真正的無界,最大值為int的最大值)

線程的六種狀態(tài)

新建狀態(tài)(new)全部代碼運行完畢

線程池

核心原理

  1. 創(chuàng)建一個池子,池子中是空的

  2. 提交任務時,池子會創(chuàng)建新的線程對象,任務執(zhí)行完畢,線程歸還給池子,下回再次提交任務時,不需要創(chuàng)建新的線程,直接復用已有的線程即可

  3. 但是如果提交任務時,池子中沒有空閑線程,也無法創(chuàng)建新的線程,任務就會排隊等待

代碼實現(xiàn):

  1. 創(chuàng)建線程池

  2. 提交任務

  3. 所有任務全部執(zhí)行完畢,關閉線程池

Executors:線程池的工具類,通過調(diào)用方法返回不同類型的線程池對象

自定義線程池

線程池多大合適?

  • CPU密集型運算:最大并行數(shù)+1 +1的目的是當前面線程出問題時可以頂上去

  • IO密集型運算:最大并行數(shù)$\times$期望CPU利用率$\times\frac{總時間(CPU計算時間+等待時間)}{CPU計算時間}$

4核8線程最大并行數(shù)為8

多線程的額外擴展

見阿瑋老師的多線程(額外擴展).md,含樂觀鎖,悲觀鎖,volatile關鍵字,原子性,一些并發(fā)工具類

Java 多線程的評論 (共 條)

分享到微博請遵守國家法律
三都| 华阴市| 汉阴县| 久治县| 大渡口区| 澳门| 三明市| 阿拉善右旗| 青田县| 泰顺县| 东至县| 无锡市| 微山县| 青浦区| 临江市| 乐都县| 东辽县| 德钦县| 额敏县| 繁峙县| 贞丰县| 长宁县| 琼海市| 扶沟县| 平顺县| 潼南县| 增城市| 临猗县| 邵阳市| 金寨县| 威信县| 玉林市| 沁源县| 河曲县| 丰镇市| 阳西县| 阿拉尔市| 石棉县| 巍山| 和林格尔县| 莱州市|