小豬學(xué)習(xí)

小小白慢慢學(xué)習(xí)中ing 第二十九天
努力努力
本日內(nèi)容(線程的兩種啟動方式、線程的常用方法、線程的狀態(tài)、臨界資源的安全問題、同步synchronized)
1、線程的兩種啟動方式
Thread類:JDK提供好的類,用于表示一個(gè)線程對象。實(shí)現(xiàn)類Runnable接口
????????????????????run(),start()....
Runnable接口:定義了唯一的一個(gè)方法:run()——>線程體
方法一:直接繼承Thread類
????????????step1:創(chuàng)建一個(gè)子類,來繼承Thread類
????????????step2:重寫run()方法,因?yàn)檫@是線程體:當(dāng)CPU調(diào)度執(zhí)行該線程的時(shí)候,就要執(zhí)行的是run()方法中的代碼。
????????????????step3:創(chuàng)建該類的對象,表示一個(gè)線程,調(diào)用start()進(jìn)而啟動這個(gè)線程。意味著該線程一切準(zhǔn)備就緒,隨時(shí)可以被CPU調(diào)度執(zhí)行。但是CPU是否立刻執(zhí)行?不一定,要看CPU自己。
方法二:實(shí)現(xiàn)Runnable接口
????????????step1:創(chuàng)建一個(gè)實(shí)現(xiàn)類,實(shí)現(xiàn)Runnable接口
????????????step2:重寫run()方法
????????????step3:先創(chuàng)建該實(shí)現(xiàn)類對象:mt,根據(jù)實(shí)現(xiàn)類對象再創(chuàng)建Thread對象,然后啟動。
Thread類的構(gòu)造方法:
????????????Thread();//創(chuàng)建一個(gè)線程對象,執(zhí)行run()。線程的默認(rèn)名:Thread-0,1,2...
????????????Thread(Runnable target);//創(chuàng)建一個(gè)線程對象,指明了target,執(zhí)行的run是Runnable接口中。
????????????Thread(String name);//創(chuàng)建一個(gè)線程,并給起個(gè)名字
????????????Thread(Runnable target,String name);
對比兩種創(chuàng)建并啟動線程的方式:

2、線程的常用方法
關(guān)于Thread類的常用方法:
????????1、獲取當(dāng)前的線程對象:由Thread類直接調(diào)用,獲取當(dāng)前正在被執(zhí)行的那個(gè)線程
????????????static Thread currentThread() ;//返回對當(dāng)前正在執(zhí)行的線程對象的引用。 ?
????????2、線程的名字:當(dāng)一個(gè)線程創(chuàng)建的時(shí)候,如果沒有設(shè)置名稱:構(gòu)造方法設(shè)置,或者setName()設(shè)置。系統(tǒng)默認(rèn) 的:Thread-0,Thread-1,Thread-2......
????????String getName()
????????返回此線程的名稱。
????????void setName(String name)
????????將此線程的名稱更改為等于參數(shù) name 。
????????3、線程的Id:每個(gè)線程創(chuàng)建的時(shí)候,由系統(tǒng)自動分配一個(gè)Id,long類型的數(shù)值,終身不變。從線程的出生到死 亡。
???????該Id值,由系統(tǒng)自動分配,程序員無法手動操作。
????????long getId()
????????返回此線程的標(biāo)識符。
????????4、線程的優(yōu)先級:priority
??????????System.out.println("最大優(yōu)先級:"+Thread.MAX_PRIORITY);//10
? ? ? ? ? System.out.println("最小優(yōu)先級:"+Thread.MIN_PRIORITY);//1
????????System.out.println("正常優(yōu)先級:"+Thread.NORM_PRIORITY);//5
????????當(dāng)一個(gè)線程被創(chuàng)建的時(shí)候,由系統(tǒng)自動分配一個(gè)優(yōu)先級,固定都是正常優(yōu)先級:5
????????但是程序員可以根據(jù)需求,手動調(diào)整線程的優(yōu)先級。
???????????????int getPriority()
????????返回此線程的優(yōu)先級
???????????void setPriority(int newPriority)
????????更改此線程的優(yōu)先級。
有個(gè)坑:容易誤解為:優(yōu)先級別高的先執(zhí)行,然后再執(zhí)行優(yōu)先級低的。大大的錯(cuò)誤XXXXX
? ? 優(yōu)先級別高,被CPU調(diào)度執(zhí)行的機(jī)會就多。但是不絕對。
? ?優(yōu)先級別低,被CPU執(zhí)行的機(jī)會就少,但是也不絕對。
5、線程的睡眠:重要的方法
? ?static void sleep(long millis)
使當(dāng)前正在執(zhí)行的線程以指定的毫秒數(shù)暫停(暫時(shí)停止執(zhí)行),具體取決于系統(tǒng)定時(shí)器和調(diào)度程序的精度和準(zhǔn)確性。
? ?靜態(tài)方法,應(yīng)該由類直接調(diào)用,對象也可以調(diào)用,有坑:不是誰調(diào)用就誰睡,而是當(dāng)前正在執(zhí)行的線程進(jìn)入睡眠了。和誰調(diào)用無關(guān)。
阻塞:
6、線程合并
? ?void join()
等待這個(gè)線程死亡。
? t1線程,t2線程,main線程
? ?t1,t2,main--->3條線程搶占資源
? 某一個(gè)時(shí)刻:main線程中:t1.join(),主線程要等待t1線程死亡之后再執(zhí)行
? ?t1,t2--->2條線程搶占資源,main等
? ?t1結(jié)束后,main線程再執(zhí)行
阻塞:
? ?Scanner scan = new Scanner(System.in);
scan.nextInt();//阻塞式。等--->解除阻塞,讀取到一個(gè)鍵盤輸人
7、守護(hù)線程
? ?setDaemon();
為前臺線程服務(wù),如果所有的前臺線程都結(jié)束了,那么守護(hù)線程也就結(jié)束了。
GC:垃圾自動回收機(jī)制。JVM啟動后,創(chuàng)建主線程執(zhí)行main()的時(shí)候。。。隨之而創(chuàng)建并啟動的還有很多后臺線程,比如gc()
3、線程的狀態(tài)
線程的生命周期:5種,6種,7種。
線程的一生,就好比秀女的一聲。
線程new出來:新建
準(zhǔn)備就緒,啟動:start:就緒狀態(tài)
如果被CPU調(diào)度執(zhí)行:運(yùn)行狀態(tài),run()方法
阻塞狀態(tài):-->進(jìn)入就緒
出生-->就緒-->運(yùn)行-->死亡
4、臨界資源的安全問題
????多個(gè)線程訪問共享的數(shù)據(jù),臨界資源。
????多個(gè)線程之間存在共享的數(shù)據(jù)。一條線程執(zhí)行過程中,其他線程也可以訪問,可能會修改數(shù)據(jù)的值。造成的共享數(shù)據(jù)的不安全。叫做臨界資源的安全問題。

5、同步synchronized
同步:原子性操作。同步起來的代碼,一次只能被1個(gè)線程執(zhí)行完畢,這個(gè)過程中,不能被其他的線程插入執(zhí)行。
同步的原理:
對象的"互斥鎖"。每個(gè)對象都可以看做一個(gè)鎖。有兩種狀態(tài):打開(默認(rèn)),關(guān)閉。
鎖對象:多條線程功能訪問的同一個(gè)對象。
t1,t2,t3,t4--->共同的一把鎖頭(同一個(gè)對象)

同步的方式一:同步代碼塊
synchronized(鎖對象){//上鎖
//被同步的代碼,每次只能被一個(gè)線程執(zhí)行,中間不能被其他線程插入執(zhí)行
}//鎖打開

注意點(diǎn):
同步的原理:鎖定一個(gè)對象。(對象可以和程序無關(guān),但必須是多個(gè)線程訪問的共同的對象才可以)。
常用的鎖對象:
this,創(chuàng)建一個(gè)對象,傳入進(jìn)去。
? ? 大招:類名.class,字符串常量:"abc"