Java20-day11【实现多线程(进程、线程-调度-控制-生命周期)、线程同步(同步代码块、线程安全、Lock)、生产者消费者(模式概述、案例)】
- 視頻+資料【鏈接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg? ?提取碼:zjxs】
- Java基礎(chǔ)--學(xué)習(xí)筆記(零起點(diǎn)打開java世界的大門)--博客匯總表
? ?? ??
目? ?錄
01_進(jìn)程和線程
1.1、進(jìn)程
1.2、線程
02_繼承Thread類的方式實(shí)現(xiàn)多線程
1.3、多線程的實(shí)現(xiàn)方式
03_設(shè)置和獲取線程名稱
1.4、設(shè)置和獲取線程名稱
04_線程優(yōu)先級(jí)
1.5、線程調(diào)度
05_線程控制
1.6、線程控制
06_線程的生命周期
1.7、線程生命周期
07_實(shí)現(xiàn)Runnable接口的方式實(shí)現(xiàn)多線程
1.8、多線程的實(shí)現(xiàn)方式
08_賣票
案例:賣票
09_賣票案例的思考
2.1、賣票案例的思考
10_同步代碼塊解決數(shù)據(jù)安全問(wèn)題
2.2、賣票案例數(shù)據(jù)安全問(wèn)題的解決
2.3、同步代碼塊
11_同步方法解決數(shù)據(jù)安全問(wèn)題
2.4、同步方法
12_線程安全的類
2.5、線程安全的類
13_Lock鎖
2.6、Lock鎖
14_生產(chǎn)者和消費(fèi)者模式概述
3.1、生產(chǎn)者和消費(fèi)者模式概述
15_生產(chǎn)者和消費(fèi)者案例
3.2、生產(chǎn)者和消費(fèi)者案例
01_進(jìn)程和線程
1.1、進(jìn)程
進(jìn)程:是正在運(yùn)行的程序。
- 是系統(tǒng)進(jìn)行資源分配和調(diào)用的獨(dú)立單位。
- 每一個(gè)進(jìn)程都有它自己的內(nèi)存空間和系統(tǒng)資源。
線程依賴于進(jìn)程而存在。
在一個(gè)進(jìn)程內(nèi)部,可以執(zhí)行一個(gè)或多個(gè)任務(wù),每個(gè)任務(wù)可以看成一個(gè)線程。
1.2、線程
線程:是進(jìn)程中的單個(gè)順序控制流,是一條執(zhí)行路徑。
- 單線程:一個(gè)進(jìn)程如果只有一條執(zhí)行路徑,則稱為單線程程序。
- 多線程:一個(gè)進(jìn)程如果有多條執(zhí)行路徑,則稱為多線程程序。
舉例:
- 記事本程序
- 掃雷程序
????掃雷:多線程
02_繼承Thread類的方式實(shí)現(xiàn)多線程
1.3、多線程的實(shí)現(xiàn)方式
方式1:繼承Thread類
- 定義一個(gè)類MyThread繼承Thread類
- 在MyThread類中重寫run()方法:MyThread類中可能還有其它的代碼,并不是所有的代碼都要被線程執(zhí)行。區(qū)分可以被線程執(zhí)行的代碼,Java提供了run()方法,用來(lái)封裝被線程執(zhí)行的代碼。
- 創(chuàng)建MyThread類的對(duì)象
- 啟動(dòng)線程
兩個(gè)小問(wèn)題:
- 為什么要重寫run()方法?
因?yàn)閞un()是用來(lái)封裝被線程執(zhí)行的代碼。
- run()方法和start()方法的區(qū)別?
run():封裝線程執(zhí)行的代碼,直接調(diào)用,相當(dāng)于普通方法的調(diào)用。
start():啟動(dòng)線程;然后由JVM調(diào)用此線程的run()方法。
03_設(shè)置和獲取線程名稱
1.4、設(shè)置和獲取線程名稱
Thread類中設(shè)置和獲取線程名稱的方法:
- void setName(String name):將此線程的名稱更改為等于參數(shù)name。
- String getName():返回此線程的名稱。
- 通過(guò)構(gòu)造方法也可以設(shè)置線程名稱。
如何獲取main()方法所在的線程名稱?
- public static Thread currentThread():返回對(duì)當(dāng)前正在執(zhí)行的線程對(duì)象的引用。
Thread部分源碼:
private String name;public Thread() {this(null, null, "Thread-" + nextThreadNum(), 0); }public Thread(String name) {this(null, null, name, 0); }public Thread(ThreadGroup group, Runnable target, String name,long stackSize) {this(group, target, name, stackSize, null, true); }private Thread(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {this.name = name; }public final synchronized void setName(String name) {this.name = name; }public final String getName() {return name; }private static int threadInitNumber; //0,1,2 private static synchronized int nextThreadNum() {return threadInitNumber++;//0,1,... }使用帶參構(gòu)造方法,需要在自己定義的MyThread類中 定義 帶參構(gòu)造方法,通過(guò)super()訪問(wèn)父類的帶參構(gòu)造方法:
獲取main()方法 當(dāng)前正在執(zhí)行的線程對(duì)象的名稱:【名為main的線程】
04_線程優(yōu)先級(jí)
1.5、線程調(diào)度
線程調(diào)度有兩種調(diào)度方式:
- 分時(shí)調(diào)度模型:所有線程輪流使用 CPU 的使用權(quán),平均分配每個(gè)線程占用 CPU 的時(shí)間片。
- 搶占式調(diào)度模型:優(yōu)先讓優(yōu)先級(jí)高的線程使用CPU,如果線程的優(yōu)先級(jí)相同,那么會(huì)隨機(jī)選擇一個(gè),優(yōu)先級(jí)高的線程獲取的CPU時(shí)間片相對(duì)多一些。
Java使用的是搶占式調(diào)度模型。
隨機(jī)性:
假如計(jì)算機(jī)只有一個(gè)CPU,那么CPU在某一個(gè)時(shí)刻只能執(zhí)行一條指令,線程只有得到CPU時(shí)間片,也就是使用權(quán),才可以執(zhí)行指令。所以說(shuō)多線程程序的執(zhí)行是有隨機(jī)性,因?yàn)檎l(shuí)搶到CPU的使用權(quán)是不一 定的。
Thread類中設(shè)置和獲取線程優(yōu)先級(jí)的方法(優(yōu)先級(jí)相關(guān)方法):
- public final int getPriority():返回此線程的優(yōu)先級(jí)。
- public final void setPriority(int newPriority):更改此線程的優(yōu)先級(jí)。線程默認(rèn)優(yōu)先級(jí)是5;線程優(yōu)先級(jí)的范圍是:1-10。
線程默認(rèn)優(yōu)先級(jí)是5;線程優(yōu)先級(jí)的范圍是:1-10
線程優(yōu)先級(jí)高僅僅表示線程獲取的CPU時(shí)間片的幾率高,但是要在次數(shù)比較多,或者多次運(yùn)行的時(shí)候才能看到你想要的效果。
05_線程控制
1.6、線程控制
如果有一個(gè)線程對(duì)象調(diào)用了join()方法,其它的線程必須等這個(gè)線程執(zhí)行完畢,其它的線程才有機(jī)會(huì)執(zhí)行。
如果主線程執(zhí)行完畢,剩下的線程全是守護(hù)線程的情況下,不會(huì)等到守護(hù)線程全部執(zhí)行完,因?yàn)镴ava虛擬機(jī)會(huì)退出。
sleep()演示:
join()演示:?
setDaemon()演示:
“劉備”線程執(zhí)行完畢之后,Java虛擬機(jī)退出(“關(guān)羽”線程、“張飛”線程 停止),需要一定的時(shí)間!
06_線程的生命周期
1.7、線程生命周期
線程一共有五種狀態(tài),線程在各種狀態(tài)之間轉(zhuǎn)換。? ?線程生命周期:線程從生到死的過(guò)程。
07_實(shí)現(xiàn)Runnable接口的方式實(shí)現(xiàn)多線程
1.8、多線程的實(shí)現(xiàn)方式
方式2:實(shí)現(xiàn)Runnable接口:
多線程的實(shí)現(xiàn)方案有兩種:
- 繼承Thread類
- 實(shí)現(xiàn)Runnable接口
相比繼承Thread類,實(shí)現(xiàn)Runnable接口的好處:
- 避免了Java單繼承的局限性。
- 適合多個(gè)相同程序的代碼去處理同一個(gè)資源的情況,把線程和程序的代碼、數(shù)據(jù)有效分離,較好的體現(xiàn)了面向?qū)ο蟮脑O(shè)計(jì)思想。
MyRunnable沒(méi)有繼承Thread類的好處:MyRunnable將來(lái)可以有自己的父類(不影響繼承其它類);可將MyRunnable看成一個(gè)資源,由多個(gè)線程去使用。
08_賣票
?
案例:賣票
? ??
09_賣票案例的思考
2.1、賣票案例的思考
剛才講解了電影院賣票程序,好像沒(méi)有什么問(wèn)題。但是在實(shí)際生活中,售票時(shí)出票也是需要時(shí)間的,所以,在出售一張票的時(shí)候,需要一點(diǎn)時(shí)間的延遲,接下來(lái)我們?nèi)バ薷馁u票程序中賣票的動(dòng)作:每次出票時(shí)間100毫秒,用sleep()方法實(shí)現(xiàn)。
賣票出現(xiàn)了問(wèn)題
- 相同的票出現(xiàn)了多次。
- 出現(xiàn)了負(fù)數(shù)的票。
問(wèn)題產(chǎn)生原因
- 線程執(zhí)行的隨機(jī)性導(dǎo)致的。
10_同步代碼塊解決數(shù)據(jù)安全問(wèn)題
2.2、賣票案例數(shù)據(jù)安全問(wèn)題的解決
為什么出現(xiàn)問(wèn)題?(安全問(wèn)題出現(xiàn)的條件)(這也是我們判斷多線程程序是否會(huì)有數(shù)據(jù)安全問(wèn)題的標(biāo)準(zhǔn))
- 是否是多線程環(huán)境
- 是否有共享數(shù)據(jù)
- 是否有多條語(yǔ)句操作共享數(shù)據(jù)
如何解決多線程安全問(wèn)題呢?
- 基本思想:讓程序沒(méi)有安全問(wèn)題的環(huán)境。
怎么實(shí)現(xiàn)呢?
- 把多條語(yǔ)句操作共享數(shù)據(jù)的代碼給鎖起來(lái),讓任意時(shí)刻只能有一個(gè)線程執(zhí)行即可。
- Java提供了同步代碼塊的方式來(lái)解決。
2.3、同步代碼塊
鎖多條語(yǔ)句操作共享數(shù)據(jù),可以使用同步代碼塊實(shí)現(xiàn)。
- 格式:
synchronized(任意對(duì)象) {
? ? ? 多條語(yǔ)句操作共享數(shù)據(jù)的代碼
}
- synchronized(任意對(duì)象):就相當(dāng)于給代碼加鎖了,任意對(duì)象就可以看成是一把鎖。
同步的好處和弊端:
- 好處:解決了多線程的數(shù)據(jù)安全問(wèn)題。
- 弊端:當(dāng)線程很多時(shí),因?yàn)槊總€(gè)線程都會(huì)去判斷同步上的鎖,這是很耗費(fèi)資源的,無(wú)形中會(huì)降低程序的運(yùn)行效率。
(把多條語(yǔ)句操作共享數(shù)據(jù)的代碼給鎖起來(lái))使用同一把鎖🔒:
11_同步方法解決數(shù)據(jù)安全問(wèn)題
2.4、同步方法
同步方法的格式
同步方法:就是把synchronized關(guān)鍵字加到方法上。
- 格式:
修飾符 synchronized 返回值類型 方法名(方法參數(shù)) { 方法體; }
同步方法的鎖對(duì)象是什么呢?
- this
靜態(tài)同步方法
同步靜態(tài)方法:就是把synchronized關(guān)鍵字加到靜態(tài)方法上。
- 格式:
修飾符 static synchronized 返回值類型 方法名(方法參數(shù)) { 方法體; }
同步靜態(tài)方法的鎖對(duì)象是什么呢?
- 類名.class
if中的代碼塊與else中的代碼塊,完全一樣!程序不會(huì)有問(wèn)題!
運(yùn)行結(jié)果同上。
同步方法:就是把synchronized關(guān)鍵字加到方法上。相當(dāng)于對(duì)方法的內(nèi)部進(jìn)行鎖定。this代表本類。
? ?
同步方法的鎖對(duì)象是什么呢?this
? ?
if代碼塊加鎖,static靜態(tài)方法沒(méi)有加鎖!--> 報(bào)錯(cuò)!--> 給靜態(tài)方法加鎖!
同步靜態(tài)方法:就是把synchronized關(guān)鍵字加到靜態(tài)方法上。
if代碼塊中加鎖(this:指代非靜態(tài)方法的鎖對(duì)象)
12_線程安全的類
2.5、線程安全的類
StringBuffer
- 線程安全,可變的字符序列。
- 從版本JDK 5開始,被StringBuilder替代。通常應(yīng)該使用StringBuilder類,因?yàn)樗С炙邢嗤牟僮?#xff0c;但它更快,因?yàn)樗粓?zhí)行同步。
Vector
- 從Java 2平臺(tái)v1.2開始,該類改進(jìn)了List接口,使其成為Java Collections Framework的成員。與新的集合實(shí)現(xiàn)不同,Vector被同步。如果不需要線程安全的實(shí)現(xiàn),建議使用ArrayList代替Vector。
Hashtable
- 該類實(shí)現(xiàn)了一個(gè)哈希表,它將鍵映射到值。任何非null對(duì)象都可以用作鍵或者值。
- 從Java 2平臺(tái)v1.2開始,該類進(jìn)行了改進(jìn),實(shí)現(xiàn)了Map接口,使其成為Java Collections Framework的成員。與新的集合實(shí)現(xiàn)不同,Hashtable被同步。如果不需要線程安全的實(shí)現(xiàn),建議使用HashMap代替Hashtable。
13_Lock鎖
2.6、Lock鎖
雖然我們可以理解同步代碼塊和同步方法的鎖對(duì)象問(wèn)題,但是我們并沒(méi)有直接看到在哪里加上了鎖,在哪里釋放了鎖,為了更清晰的表達(dá)如何加鎖和釋放鎖,JDK5以后提供了一個(gè)新的鎖對(duì)象Lock。
Lock實(shí)現(xiàn)提供比使用synchronized方法和語(yǔ)句可以獲得更廣泛的鎖定操作。
Lock中提供了獲得鎖和釋放鎖的方法:
- void lock() 獲得鎖
- void unlock() 釋放鎖
Lock是接口不能直接實(shí)例化,這里采用它的實(shí)現(xiàn)類ReentrantLock來(lái)實(shí)例化。
ReentrantLock的構(gòu)造方法
- ReentrantLock():創(chuàng)建一個(gè)ReentrantLock的實(shí)例
?
????
14_生產(chǎn)者和消費(fèi)者模式概述
3.1、生產(chǎn)者和消費(fèi)者模式概述
15_生產(chǎn)者和消費(fèi)者案例
3.2、生產(chǎn)者和消費(fèi)者案例
? ??
Box.java:
package com.itheima_12;public class Box {//定義一個(gè)成員變量,表示第x瓶奶private int milk;//定義一個(gè)成員變量,表示奶箱的狀態(tài)private boolean state = false; // 默認(rèn)沒(méi)有牛奶🥛//提供存儲(chǔ)牛奶和獲取牛奶的操作public synchronized void put(int milk) {//如果有牛奶,等待消費(fèi)if (state) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果沒(méi)有牛奶,就生產(chǎn)牛奶this.milk = milk;System.out.println("送奶工將第" + this.milk + "瓶奶放入奶箱");//生產(chǎn)完畢之后,修改奶箱狀態(tài)state = true;//喚醒其他等待的線程notifyAll();}public synchronized void get() {//如果沒(méi)有牛奶,等待生產(chǎn)if (!state) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果有牛奶,就消費(fèi)牛奶System.out.println("用戶拿到第" + this.milk + "瓶奶");//消費(fèi)完畢之后,修改奶箱狀態(tài)state = false;//喚醒其他等待的線程notifyAll();} }蟹蟹觀看~
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Java20-day11【实现多线程(进程、线程-调度-控制-生命周期)、线程同步(同步代码块、线程安全、Lock)、生产者消费者(模式概述、案例)】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2014年 第5届 蓝桥杯 Java B
- 下一篇: Java21-day12【网络编程(网络