------- android培訓(xùn)、java培訓(xùn)、期待與您交流! ----------
成都創(chuàng)新互聯(lián)2013年開創(chuàng)至今,先為海珠等服務(wù)建站,海珠等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為海珠企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
進(jìn)程:正在執(zhí)行的程序。
線程:是進(jìn)程中用于控制程序執(zhí)行的控制單元(執(zhí)行路徑,執(zhí)行情景),進(jìn)程中至少有一個線程。
對于JVM,啟動時,只好有兩個線程:jvm的主線程。jvm的垃圾回收線程。
如何在程序中自定義線程呢?
Java給我們提供了對象線程這類事物的描述。該類是Thread。該類中定義了,創(chuàng)建線程對象的方法(構(gòu)造函數(shù)),提供了要被線程執(zhí)行的代碼存儲的位置(run());還定義了開啟線程運行的方法(start()).同時還有一些其他的方法用于操作線程:static Thread currentThead();String getName();static void sleep(time)throws InterruptedException;要運行的代碼都是后期定義的。
創(chuàng)建線程的第一種方式是:繼承Thread類。原因:要覆蓋run方法,定義線程要運行的代碼。
步驟:
1,繼承Thread類。
2,覆蓋run方法。將線程要運行的代碼定義其中。
3,創(chuàng)建Thread類的子類對象,其實就是在創(chuàng)建線程,調(diào)用start方法。
創(chuàng)建線程的第二種方式:實現(xiàn)Runnable接口。
步驟:
1,定義了實現(xiàn)Runnable接口。
2,覆蓋接口的run方法。將多線程要運行的代碼存入其中。
3,創(chuàng)建Thread類的對象(創(chuàng)建線程),并將Runnable接口的子類對象作為參數(shù)傳遞給Thread的構(gòu)造函數(shù)。
為什么要傳遞?因為線程要運行的代碼都在Runnable子類的run方法中存儲。所以要將該run方法所屬的對象傳遞給Thread。讓Thread線程去使用該對象調(diào)用其run方法。
4,調(diào)用Thread對象的start方法。開啟線程。
兩種方式的特點:
實現(xiàn)方式,因為避免了單繼承的局限性,所以創(chuàng)建線程建議使用第二種方式。
線程狀態(tài):
被創(chuàng)建:start()
運行:具備執(zhí)行資格,同時具備執(zhí)行權(quán);
凍結(jié):sleep(time),wait()—notify()喚醒;線程釋放了執(zhí)行權(quán),同時釋放執(zhí)行資格;
臨時阻塞狀態(tài):線程具備cpu的執(zhí)行資格,沒有cpu的執(zhí)行權(quán);
消亡:stop()
多線程具備隨機性。因為是由cpu不斷的快速切換造成的。就有可能會產(chǎn)生多線程的安全問題。
問題的產(chǎn)生的原因:
幾個關(guān)鍵點:
1,多線程代碼中有操作共享數(shù)據(jù)。
2,多條語句操作該共享數(shù)據(jù)。
當(dāng)具備兩個關(guān)鍵點時,有一個線程對多條操作共享數(shù)據(jù)的代碼執(zhí)行的一部分。還沒有執(zhí)行完,另一個線程開始參與執(zhí)行。就會發(fā)生數(shù)據(jù)錯誤。
解決方法:
當(dāng)一個線程在執(zhí)行多條操作共享數(shù)據(jù)代碼時,其他線程即使獲取了執(zhí)行權(quán),也不可以參與操作。
同步
同步的原理:就是將部分操作功能數(shù)據(jù)的代碼進(jìn)行加鎖。
同步的表現(xiàn)形式:
1,同步代碼塊。
2,同步函數(shù)。
兩者有什么不同:
同步代碼塊使用的鎖是任意對象。
同步函數(shù)使用的鎖是this。
注意:對于static的同步函數(shù),使用的鎖不是this。是 類名.class 是該類的字節(jié)碼文件對象。
同步的好處:解決了線程的安全問題。
弊端:較為消耗資源。同步嵌套后,容易死鎖。
要記?。和绞褂玫那疤幔?/p>
1,必須是兩個或者兩個以上的線程。
2,必須是多個線程使用同一個鎖。
這是才可以稱為這些線程被同步了。
死鎖代碼:
class Test implements Runnable { private boolean flag;//定義標(biāo)記,用于調(diào)節(jié)兩個線程的運行。 Test(boolean flag) { this.flag = flag; } public void run() { if (flag) { while (true) { synchronized(MyLock.locka) { System.out.println("if locka");//線程t1需要MyLock.lockb,但是else的MyLock.lockb內(nèi)有t2。 synchronized(MyLock.lockb) { System.out.println("if lockb"); } } } } else { while (true) { synchronized(MyLock.lockb) { System.out.println("else lockb");//線程t2需要MyLock.locka,但是if的MyLock.locka內(nèi)有t1。 synchronized(MyLock.locka) { System.out.println("else locka"); } } } } } } class MyLock { static Object locka = new Object(); static Object lockb = new Object(); } class DeadLockTest { public static void main(String[] args) { //該線程運行if語句。 Thread t1 = new Thread(new Test(true)); //該線程運行else語句。 Thread t2 = new Thread(new Test(false)); t1.start(); t2.start(); } }
java.lang.Thread 的方法
interrupt():中斷線程。
setPriority(int newPriority):更改線程的優(yōu)先級。
getPriority():返回線程的優(yōu)先級。
toString():返回該線程的字符串表示形式,包括線程名稱、優(yōu)先級和線程組。
Thread.yield():暫停當(dāng)前正在執(zhí)行的線程對象,并執(zhí)行其他線程。
setDaemon(true):將該線程標(biāo)記為守護(hù)線程或用戶線程。將該線程標(biāo)記為守護(hù)線程或用戶線程。當(dāng)正在運行的線程都是守護(hù)線程時,Java 虛擬機退出。該方法必須在啟動線程前調(diào)用。
join:臨時加入一個線程的時候可以使用join方法。當(dāng)A線程執(zhí)行到了B線程的join方式。A線程處于凍結(jié)狀態(tài),釋放了執(zhí)行權(quán),B開始執(zhí)行。A什么時候執(zhí)行呢?只有當(dāng)B線程運行結(jié)束后,A才從凍結(jié)狀態(tài)恢復(fù)運行狀態(tài)執(zhí)行。
JKD1.5中提供了多線程升級解決方案。
將同步synchronized替換成顯式的Lock操作。
將Object中的wait,notify,notifyAll,替換了Condition對象。該對象可以Lock鎖獲取。
在該示例中,實現(xiàn)了本方只喚醒對方的操作。
class Test implements Runnable { private boolean flag;//定義標(biāo)記,用于調(diào)節(jié)兩個線程的運行。 Test(boolean flag) { this.flag = flag; } public void run() { if (flag) { while (true) { synchronized(MyLock.locka) { System.out.println("if locka");//線程t1需要MyLock.lockb,但是else的MyLock.lockb內(nèi)有t2。 synchronized(MyLock.lockb) { System.out.println("if lockb"); } } } } else { while (true) { synchronized(MyLock.lockb) { System.out.println("else lockb");//線程t2需要MyLock.locka,但是if的MyLock.locka內(nèi)有t1。 synchronized(MyLock.locka) { System.out.println("else locka"); } } } } } } class MyLock { static Object locka = new Object(); static Object lockb = new Object(); } class DeadLockTest { public static void main(String[] args) { //該線程運行if語句。 Thread t1 = new Thread(new Test(true)); //該線程運行else語句。 Thread t2 = new Thread(new Test(false)); t1.start(); t2.start(); } }