進程:
正在進行中的程序(直譯)淆党。對應的是一個程序在內(nèi)存中開辟的所屬空間。
線程:
進程中的一個負責程序執(zhí)行的控制單元(執(zhí)行路徑)。一個進程中可以有多個執(zhí)行路徑趣惠,成為多線程。
一個進程中至少有一個線程身害。
開啟多個線程是為了同時運行多部分代碼味悄,每一個線程都有自己運行的內(nèi)容。這個內(nèi)容可以稱為線程要執(zhí)行的任務塌鸯。
多線程好處:解決了多部分同時運行的問題侍瑟。
多線程弊端:線程太多會導致效率的降低。
其實應用程序的執(zhí)行都是cpu在做著快速的切換完成的丙猬。這個切換是隨機的涨颜。
JVM的多線程
JVM啟動時,就啟動了多個線程茧球,至少有兩個線程可以分析的出來庭瑰。
1. 執(zhí)行main函數(shù)的線程
該線程的任務代碼都定義在main函數(shù)中
2. 負責垃圾回收的線程
繼承Thread類:
如何創(chuàng)建一個線程呢?
創(chuàng)建線程方式一:繼承Thread類
步驟:
1. 定義一個類繼承Thread類;
2. 覆蓋Thread類中的run方法
3. 直接創(chuàng)建Thread的子類對象創(chuàng)建線程
4. 調(diào)用start方法先開啟線程袜腥,并調(diào)用線程的任務run方法執(zhí)行见擦。
創(chuàng)建線程的目的是為了開啟一條執(zhí)行路徑,去運行指定的代碼和其他代碼實現(xiàn)同時運行羹令。而運行的指定代碼就是這個執(zhí)行路徑的任務鲤屡。jvm創(chuàng)建的主線程的任務都定義在了主函數(shù)中。
而自定義的線程它的任務在哪兒呢福侈?
Thread類用于描述線程酒来,線程是需要任務的。所以Thread類也有對任務的描述肪凛。這個任務就通過Thread類中的run方法來體現(xiàn)堰汉。也就是說辽社,run方法就是封裝自定義線程運行任務的函數(shù)。run方法中定義就是線程要運行的任務代碼翘鸭。
開啟線程是為了運行指定代碼滴铅。所以只有繼承Thread類,并復寫run方法就乓。將運行的代碼定義在run方法中即可汉匙。
可以通過Thread的getName獲取線程的名稱。Thread-編號(從0開始)
主線程的名字是main
線程的狀態(tài):
實現(xiàn)Runnable接口:
創(chuàng)建線程方式二:實現(xiàn)Runnable接口
1. 定義類實現(xiàn)Runnable接口
2. 覆蓋接口中的run方法生蚁,將線程的任務代碼封裝到run方法中
3. 通過Thread類創(chuàng)建線程對象噩翠,并將Runnable接口的子類對象作為構(gòu)造函數(shù)的參數(shù)進行傳遞。為什么邦投?
因為線程的任務都封裝在Runnable接口子類對象的run方法中伤锚。所以要在線程對象創(chuàng)建時就必須明確要運行的任務。
4. 調(diào)用線程對象的start方法開啟線程志衣。
實現(xiàn)Runnable接口的好處:
1. 將線程的任務從線程的子類中分離出來進行了單獨的封裝屯援。按照面向?qū)ο蟮乃枷雽⑷蝿辗庋b成對象。
2. 避免了java單繼承的局限性蠢涝。
所以創(chuàng)建線程的第二種方式較為常用玄呛。
其實,Thread類也實現(xiàn)了Runnable接口和二。
練習:
線程安全問題產(chǎn)生原因:
1. 多個線程在操作共存的數(shù)據(jù)
2. 操作共享數(shù)據(jù)的線程代碼有多條
當一個線程在執(zhí)行操作共享數(shù)據(jù)的多條代碼過程中,其他線程參與了運算耳胎,就會導致線程安全問題的產(chǎn)生惯吕。
解決思路:就是將多條操作共享數(shù)據(jù)的線程代碼封裝起來,當有線程在執(zhí)行這些代碼的時候怕午,其他線程是不可以參與運算的废登。必須要當前線程把這些代碼都執(zhí)行完畢后,其他線程才可以參與運算郁惜。
在java中堡距,用同步代碼塊就能解決這個問題。
同步synchronized:
同步代碼塊的格式:
synchronized(對象){
需要被同步的代碼兆蕉;
}
舉例:
同步的好處:解決了線程的安全問題羽戒。
同步的弊端:相對降低了效率,因為同步外的線程都會判斷同步鎖虎韵。
同步的前提:同步中必須有多個線程并使用同一個鎖易稠。
同步函數(shù):
同步函數(shù)使用的鎖是this;
同步函數(shù)和同步代碼塊的區(qū)別:
同步函數(shù)的鎖是固定的this包蓝,同步代碼塊的鎖是任意的對象驶社。建議使用同步代碼塊企量。
靜態(tài)的同步函數(shù)使用的鎖是該函數(shù)所屬字節(jié)碼文件對象⊥龅纾可以用getclass()方法獲取届巩,也可以用當前類名.class表示。
死鎖: