一与柑、基本概念:程序 - 進(jìn)程 - 線(xiàn)程
程序(program):是為完成特定任務(wù)谤辜、用某種語(yǔ)言編寫(xiě)的一組指令的集合。即指一段靜態(tài)的代碼价捧,靜態(tài)對(duì)象丑念。
進(jìn)程(process):是程序的一次執(zhí)行過(guò)程,或是正在運(yùn)行的一個(gè)程序结蟋。動(dòng)態(tài)過(guò)程:有它自身的產(chǎn)生脯倚、存在和消亡的過(guò)程。
? ? ? ? 如:運(yùn)行中的QQ,運(yùn)行中的MP3播放器
? ? ? ? 程序是靜態(tài)的推正,進(jìn)程是動(dòng)態(tài)的(加載到了內(nèi)存中)
線(xiàn)程(thread):進(jìn)程可進(jìn)一步細(xì)化為線(xiàn)程恍涂,是一個(gè)程序內(nèi)部的一條執(zhí)行路徑。
? ? ? 若一個(gè)程序可同一時(shí)間執(zhí)行多個(gè)線(xiàn)程植榕,就是支持多線(xiàn)程的
? ? ? ? 如:打開(kāi)360再沧,這時(shí)在任務(wù)管理器里面就有一個(gè) 進(jìn)程,360可以同時(shí)體驗(yàn)尊残、木馬炒瘸、系統(tǒng)修復(fù)等,這些是 線(xiàn)程;說(shuō)明360支持多線(xiàn)程寝衫。
二顷扩、什么時(shí)候需要多線(xiàn)程
1、程序需要同時(shí)執(zhí)行兩個(gè)或多個(gè)任務(wù)慰毅。
2隘截、程序需要實(shí)現(xiàn)一些需要等待的任務(wù)時(shí),如用戶(hù)輸入事富、文件讀寫(xiě)操作技俐、網(wǎng)絡(luò)操作乘陪、搜索等统台。
3、需要一些后臺(tái)運(yùn)行的程序時(shí)啡邑。
注意:每個(gè)Java程序都有一個(gè)隱含的主線(xiàn)程: main 方法贱勃;
? ? ? ? ? 一個(gè)線(xiàn)程只能夠執(zhí)行一次start()方法;
? ? ? ? ?不能通過(guò)Thread實(shí)現(xiàn)類(lèi)對(duì)象的run()方法去啟動(dòng)一個(gè)線(xiàn)程谤逼。(如下面的thread1.run() 錯(cuò)誤)
注意:此時(shí)的thread2.run() ? //使用這個(gè)方式是可以執(zhí)行贵扰,但是沒(méi)有創(chuàng)建多線(xiàn)程
三、創(chuàng)建線(xiàn)程的兩種方式
1流部、繼承Thread類(lèi)
? ?1)? 定義子類(lèi)繼承Thread類(lèi)戚绕。
? ?2)? 子類(lèi)中重寫(xiě)Thread類(lèi)中的run方法。
? ?3)? 創(chuàng)建Thread子類(lèi)對(duì)象枝冀,即創(chuàng)建了線(xiàn)程對(duì)象舞丛。
? ?4)? 調(diào)用線(xiàn)程對(duì)象start方法:?jiǎn)?dòng)線(xiàn)程,調(diào)用run方法果漾。
2.? 實(shí)現(xiàn)Runnable接口
? ?1)定義子類(lèi)球切,實(shí)現(xiàn)Runnable接口。
? ?2)子類(lèi)中重寫(xiě)Runnable接口中的run方法绒障。
? ?3)通過(guò)Thread類(lèi)含參構(gòu)造器創(chuàng)建線(xiàn)程對(duì)象吨凑。
? ?4)將Runnable接口的子類(lèi)對(duì)象作為實(shí)際參數(shù)傳遞給Thread類(lèi)的構(gòu)造方法中。
? ?5)調(diào)用Thread類(lèi)的start方法:開(kāi)啟線(xiàn)程户辱,調(diào)用Runnable子類(lèi)接口的run方法鸵钝。
? ? ? ? ? ? ? ?Thread t=new Thread(實(shí)現(xiàn)接口的對(duì)象);
? ? ? ? ? ? ? ? t.start();
四糙臼、繼承方式和實(shí)現(xiàn)方式的聯(lián)系與區(qū)別
【區(qū)別】
? ?繼承Thread:? ? ? 線(xiàn)程代碼存放Thread子類(lèi)run方法中。
? ?實(shí)現(xiàn)Runnable:線(xiàn)程代碼存在接口的子類(lèi)的run方法恩商。
【實(shí)現(xiàn)方法的好處】
? ?1)避免了單繼承的局限性
? ?2)多個(gè)線(xiàn)程可以共享同一個(gè)接口實(shí)現(xiàn)類(lèi)的對(duì)象弓摘,非常適合多個(gè)相同線(xiàn)程來(lái)處理同一份資源。
注意:以上兩個(gè)小例子存在安全隱患锤窑,時(shí)不時(shí)會(huì)出現(xiàn)重票;涉及到了線(xiàn)程的安全問(wèn)題
多線(xiàn)程出現(xiàn)了安全問(wèn)題
1 嚷炉、問(wèn)題的原因——當(dāng)多條語(yǔ)句在操作同一個(gè)線(xiàn)程共享數(shù)據(jù)時(shí)渊啰,一個(gè)線(xiàn)程對(duì)多條語(yǔ)句只執(zhí)行了一部分,還沒(méi)有執(zhí)行完申屹,另一個(gè)線(xiàn)程參與進(jìn)來(lái)執(zhí)行绘证。導(dǎo)致共享數(shù)據(jù)的錯(cuò)誤。
2 哗讥、解決辦法——對(duì)多條操作共享數(shù)據(jù)的語(yǔ)句嚷那,只能讓一個(gè)線(xiàn)程都執(zhí)行完,在執(zhí)行過(guò)程中杆煞,其他線(xiàn)程不可以參與執(zhí)行魏宽。
3 、java如何實(shí)現(xiàn)線(xiàn)程的安全:線(xiàn)程的同步機(jī)制(詳情看第十點(diǎn))
? ? ? ?方式①决乎、同步代碼快
? ? ? ?方式②队询、同步方法
五、Thread類(lèi)的有關(guān)方法
注意:線(xiàn)程通信——wait() ? ? notify() ? ? notifyAll()
1构诚、void start():? 啟動(dòng)線(xiàn)程蚌斩,并執(zhí)行對(duì)象的run()方法
2、run():? 線(xiàn)程在被調(diào)度時(shí)執(zhí)行的操作
3范嘱、String getName():? 返回線(xiàn)程的名稱(chēng)
4送膳、void setName(String name):設(shè)置該線(xiàn)程名稱(chēng)
5、static currentThread(): 返回當(dāng)前線(xiàn)程
6彤侍、static? void? yield():線(xiàn)程讓步
? ? ? ?暫停當(dāng)前正在執(zhí)行的線(xiàn)程肠缨,把執(zhí)行機(jī)會(huì)讓給優(yōu)先級(jí)相同或更高的線(xiàn)程
? ? ? ? 若隊(duì)列中沒(méi)有同優(yōu)先級(jí)的線(xiàn)程,忽略此方法
7盏阶、join() :當(dāng)某個(gè)程序執(zhí)行流中調(diào)用其他線(xiàn)程的 join() 方法時(shí)晒奕,調(diào)用線(xiàn)程將被阻塞,直到 join() 方? 法加入的 join 線(xiàn)程執(zhí)行完為止
? ? ? ? ?低優(yōu)先級(jí)的線(xiàn)程也可以獲得執(zhí)行
8、static? void? sleep(long millis):(指定時(shí)間:毫秒)
? ? 令當(dāng)前活動(dòng)線(xiàn)程在指定時(shí)間段內(nèi)放棄對(duì)CPU控制,使其他線(xiàn)程有機(jī)會(huì)被執(zhí)行,時(shí)間到后重排隊(duì)脑慧。
? ? 拋出InterruptedException異常
9魄眉、stop(): 強(qiáng)制線(xiàn)程生命期結(jié)束
10、boolean isAlive():返回boolean闷袒,判斷線(xiàn)程是否還活著
六坑律、線(xiàn)程的調(diào)度
調(diào)度策略
? ?時(shí)間片 ??
? ? 搶占式:高優(yōu)先級(jí)的線(xiàn)程搶占CPU
Java的調(diào)度方法
① 、同優(yōu)先級(jí)線(xiàn)程組成先進(jìn)先出隊(duì)列(先到先服務(wù))囊骤,使用時(shí)間片策略
② 晃择、對(duì)高優(yōu)先級(jí),使用優(yōu)先調(diào)度的搶占式策略
七也物、線(xiàn)程的優(yōu)先級(jí)
——并不是說(shuō)最先執(zhí)行優(yōu)先級(jí)高的宫屠,而是搶到的概率大了
線(xiàn)程的優(yōu)先級(jí)控制
① 、MAX_PRIORITY(10); ?最大
② 滑蚯、MIN _PRIORITY (1);
③ 浪蹂、NORM_PRIORITY (5);
涉及的方法:
? ?①、 ?getPriority() :返回線(xiàn)程優(yōu)先值
? ?②告材、 ?setPriority(int newPriority) :改變線(xiàn)程的優(yōu)先級(jí)
線(xiàn)程創(chuàng)建時(shí)繼承父線(xiàn)程的優(yōu)先級(jí)
八坤次、多線(xiàn)程的優(yōu)點(diǎn)
背景:只使用單個(gè)線(xiàn)程完成多個(gè)任務(wù)(調(diào)用多個(gè)方法),肯定比用多個(gè)線(xiàn)程來(lái)完成用的時(shí)間更短斥赋,為何仍需多線(xiàn)程呢缰猴?
舉例描述: ?我現(xiàn)在需要吧C盤(pán)數(shù)據(jù)拷貝到D盤(pán),E盤(pán)數(shù)據(jù)拷貝到F盤(pán)灿渴;
? ? ?A——先從C到D洛波,結(jié)束了過(guò)后胰舆,再E到F ? ? ? ? ? ? ? ?這個(gè)拷貝速度快
? ? ?B——執(zhí)行從C到D的同時(shí)執(zhí)行E到F ? ? ? ? ? ? ? ? ? ? ? 因?yàn)檫@個(gè)浪費(fèi)了CPU切換時(shí)間
多線(xiàn)程程序的優(yōu)點(diǎn):
1 骚露、提高應(yīng)用程序的響應(yīng)。對(duì)圖形化界面更有意義译蒂,可增強(qiáng)用戶(hù)體驗(yàn)碉渡。
2 翼闽、提高計(jì)算機(jī)系統(tǒng)CPU的利用率
3 、改善程序結(jié)構(gòu)误续。將既長(zhǎng)又復(fù)雜的進(jìn)程分為多個(gè)線(xiàn)程,獨(dú)立運(yùn)行扫茅,利于理解和修改
補(bǔ)充:線(xiàn)程的分類(lèi)
Java中的線(xiàn)程分為兩類(lèi):一種是守護(hù)線(xiàn)程蹋嵌,一種是用戶(hù)線(xiàn)程。
1 葫隙、它們?cè)趲缀趺總€(gè)方面都是相同的栽烂,唯一的區(qū)別是判斷JVM何時(shí)離開(kāi)。
2 、守護(hù)線(xiàn)程是用來(lái)服務(wù)用戶(hù)線(xiàn)程的腺办,通過(guò)在start()方法前調(diào)用thread.setDaemon(true)可以把一個(gè)用戶(hù)線(xiàn)程變成一個(gè)守護(hù)線(xiàn)程焰手。
3 、Java垃圾回收就是一個(gè)典型的守護(hù)線(xiàn)程怀喉。
4 书妻、若JVM中都是守護(hù)線(xiàn)程,當(dāng)前JVM將退出躬拢。
九躲履、線(xiàn)程的生命周期
要想實(shí)現(xiàn)多線(xiàn)程,必須在主線(xiàn)程中創(chuàng)建新的線(xiàn)程對(duì)象聊闯。Java語(yǔ)言使用Thread類(lèi)及其子類(lèi)的對(duì)象來(lái)表示線(xiàn)程崇呵,在它的一個(gè)完整的生命周期中通常要經(jīng)歷如下的五種狀態(tài):
新建: 當(dāng)一個(gè)Thread類(lèi)或其子類(lèi)的對(duì)象被聲明并創(chuàng)建時(shí),新生的線(xiàn)程對(duì)象處于新建狀態(tài)
就緒:處于新建狀態(tài)的線(xiàn)程被start()后馅袁,將進(jìn)入線(xiàn)程隊(duì)列等待CPU時(shí)間片域慷,此時(shí)它已具備了運(yùn)行的條件
運(yùn)行:當(dāng)就緒的線(xiàn)程被調(diào)度并獲得處理器資源時(shí),便進(jìn)入運(yùn)行狀態(tài), run()方法定義了線(xiàn)程的操作和功能
阻塞:在某種特殊情況下汗销,被人為掛起或執(zhí)行輸入輸出操作時(shí)犹褒,讓出 CPU 并臨時(shí)中止自己的執(zhí)行,進(jìn)入阻塞狀態(tài)
死亡:線(xiàn)程完成了它的全部工作或線(xiàn)程被提前強(qiáng)制性地中止
十弛针、Synchronized的使用方法
——java線(xiàn)程的同步機(jī)制
互斥鎖——在Java語(yǔ)言中,引入了對(duì)象互斥鎖的概念削茁,來(lái)保證共享數(shù)據(jù)操作的完整性宙枷。
1 、每個(gè)對(duì)象都對(duì)應(yīng)于一個(gè)可稱(chēng)為“互斥鎖”的標(biāo)記茧跋,這個(gè)標(biāo)記用來(lái)保證在任一時(shí)刻慰丛,只能有一個(gè)線(xiàn)程訪(fǎng)問(wèn)該對(duì)象。
2 瘾杭、關(guān)鍵字synchronized 來(lái)與對(duì)象的互斥鎖聯(lián)系诅病。當(dāng)某個(gè)對(duì)象用synchronized修飾時(shí),表明該對(duì)象在任一時(shí)刻只能由一個(gè)線(xiàn)程訪(fǎng)問(wèn)粥烁。
3 贤笆、同步的局限性:導(dǎo)致程序的執(zhí)行效率要降低
? ? ?線(xiàn)程的同步的弊端:由于同一個(gè)時(shí)間只能有一個(gè)線(xiàn)程訪(fǎng)問(wèn)共享數(shù)據(jù),所以效率變低了
4 讨阻、同步方法(非靜態(tài)的)的鎖為this芥永。
5 、同步方法(靜態(tài)的)的鎖為當(dāng)前類(lèi)本身钝吮。
十一埋涧、小結(jié)
釋放鎖的操作
1 贴唇、當(dāng)前線(xiàn)程的同步方法、同步代碼塊執(zhí)行結(jié)束
2 飞袋、當(dāng)前線(xiàn)程在同步代碼塊戳气、同步方法中遇到break、return終止了該代碼塊巧鸭、該方法的繼續(xù)執(zhí)行瓶您。
3 、當(dāng)前線(xiàn)程在同步代碼塊纲仍、同步方法中出現(xiàn)了未處理的Error或Exception呀袱,導(dǎo)致異常結(jié)束
4 、當(dāng)前線(xiàn)程在同步代碼塊郑叠、同步方法中執(zhí)行了線(xiàn)程對(duì)象的wait()方法夜赵,當(dāng)前線(xiàn)程暫停,并釋放鎖乡革。
不會(huì)釋放鎖的操作
1 寇僧、線(xiàn)程執(zhí)行同步代碼塊或同步方法時(shí),程序調(diào)用Thread.sleep()沸版、Thread.yield()方法暫停當(dāng)前線(xiàn)程的執(zhí)行
2 嘁傀、線(xiàn)程執(zhí)行同步代碼塊時(shí),其他線(xiàn)程調(diào)用了該線(xiàn)程的suspend()方法將該線(xiàn)程掛起视粮,該線(xiàn)程不會(huì)釋放鎖(同步監(jiān)視器)细办。——應(yīng)盡量避免使用suspend()和resume()來(lái)控制線(xiàn)程
線(xiàn)程的死鎖問(wèn)題
——死鎖
不同的線(xiàn)程分別占用對(duì)方需要的同步資源不放棄蕾殴,都在等待對(duì)方放棄自己需要的同步資源笑撞,就形成了線(xiàn)程的死鎖
——解決方法
1 、專(zhuān)門(mén)的算法钓觉、原則
2 茴肥、盡量減少同步資源的定義
上面這個(gè)例子——兩個(gè)用戶(hù)存錢(qián)是隨機(jī)存入的!
拓展問(wèn)題:可否實(shí)現(xiàn)兩個(gè)儲(chǔ)戶(hù)交替存錢(qián)的操作议谷。需要使用 線(xiàn)程通信炉爆!
十二、線(xiàn)程通信
wait() 與 notify() 和 notifyAll()
wait():令當(dāng)前線(xiàn)程掛起并放棄CPU卧晓、同步資源,使別的線(xiàn)程可訪(fǎng)問(wèn)并修改共享資源赴捞,而當(dāng)前線(xiàn)程排隊(duì)等候再次對(duì)資源的訪(fǎng)問(wèn)
notify():喚醒正在排隊(duì)等待同步資源的線(xiàn)程中優(yōu)先級(jí)最高者結(jié)束等待
notifyAll ():喚醒正在排隊(duì)等待資源的所有線(xiàn)程結(jié)束等待.
Java.lang.Object提供的這三個(gè)方法只有在synchronized方法或synchronized代碼塊中才能使用逼裆,否則會(huì)報(bào)java.lang.IllegalMonitorStateException異常
wait() 方法
1 、在當(dāng)前線(xiàn)程中調(diào)用方法:? 對(duì)象名.wait()
2 赦政、使當(dāng)前線(xiàn)程進(jìn)入等待(某對(duì)象)狀態(tài) 胜宇,直到另一線(xiàn)程對(duì)該對(duì)象發(fā)出 notify (或notifyAll) 為止耀怜。
3 、調(diào)用方法的必要條件:當(dāng)前線(xiàn)程必須具有對(duì)該對(duì)象的監(jiān)控權(quán)(加鎖)
4 桐愉、調(diào)用此方法后财破,當(dāng)前線(xiàn)程將釋放對(duì)象監(jiān)控權(quán)? ,然后進(jìn)入等待
5 从诲、在當(dāng)前線(xiàn)程被notify后左痢,要重新獲得監(jiān)控權(quán),然后從斷點(diǎn)處繼續(xù)代碼的執(zhí)行系洛。
notify()/notifyAll()
1 俊性、在當(dāng)前線(xiàn)程中調(diào)用方法:? 對(duì)象名.notify()
2 、功能:?jiǎn)拘训却搶?duì)象監(jiān)控權(quán)的一個(gè)線(xiàn)程描扯。
3 定页、調(diào)用方法的必要條件:當(dāng)前線(xiàn)程必須具有對(duì)該對(duì)象的監(jiān)控權(quán)(加鎖)