------- android教育訓練、java教育訓練、期待與您交流! ----------
程序:正在執行的程式。
線程:是程序中用于控制程式執行的控制單元(執行路徑,執行情景),程序中至少有一個線程。
對于JVM,啟動時,隻好有兩個線程:jvm的主線程。jvm的垃圾回收線程。
如何在程式中自定義線程呢?
Java給我們提供了對象線程這類事物的描述。該類是Thread。該類中定義了,建立線程對象的方法(構造函數),提供了要被線程執行的代碼存儲的位置(run());還定義了開啟線程運作的方法(start()).同時還有一些其他的方法用于操作線程:static Thread currentThead();String getName();static void sleep(time)throws InterruptedException;要運作的代碼都是後期定義的。
建立線程的第一種方式是:繼承Thread類。原因:要覆寫run方法,定義線程要運作的代碼。
步驟:
1,繼承Thread類。
2,覆寫run方法。将線程要運作的代碼定義其中。
3,建立Thread類的子類對象,其實就是在建立線程,調用start方法。
建立線程的第二種方式:實作Runnable接口。
步驟:
1,定義了實作Runnable接口。
2,覆寫接口的run方法。将多線程要運作的代碼存入其中。
3,建立Thread類的對象(建立線程),并将Runnable接口的子類對象作為參數傳遞給Thread的構造函數。
為什麼要傳遞?因為線程要運作的代碼都在Runnable子類的run方法中存儲。是以要将該run方法所屬的對象傳遞給Thread。讓Thread線程去使用該對象調用其run方法。
4,調用Thread對象的start方法。開啟線程。
兩種方式的特點:
實作方式,因為避免了單繼承的局限性,是以建立線程建議使用第二種方式。
線程狀态:
被建立:start()
運作:具備執行資格,同時具備執行權;
當機:sleep(time),wait()—notify()喚醒;線程釋放了執行權,同時釋放執行資格;
臨時阻塞狀态:線程具備cpu的執行資格,沒有cpu的執行權;
消亡:stop()

多線程具備随機性。因為是由cpu不斷的快速切換造成的。就有可能會産生多線程的安全問題。
問題的産生的原因:
幾個關鍵點:
1,多線程代碼中有操作共享資料。
2,多條語句操作該共享資料。
當具備兩個關鍵點時,有一個線程對多條操作共享資料的代碼執行的一部分。還沒有執行完,另一個線程開始參與執行。就會發生資料錯誤。
解決方法:
當一個線程在執行多條操作共享資料代碼時,其他線程即使擷取了執行權,也不可以參與操作。
同步
同步的原理:就是将部分操作功能資料的代碼進行加鎖。
同步的表現形式:
1,同步代碼塊。
2,同步函數。
兩者有什麼不同:
同步代碼塊使用的鎖是任意對象。
同步函數使用的鎖是this。
注意:對于static的同步函數,使用的鎖不是this。是 類名.class 是該類的位元組碼檔案對象。
同步的好處:解決了線程的安全問題。
弊端:較為消耗資源。同步嵌套後,容易死鎖。
要記住:同步使用的前提:
1,必須是兩個或者兩個以上的線程。
2,必須是多個線程使用同一個鎖。
這是才可以稱為這些線程被同步了。
死鎖代碼:
class Test implements Runnable
{
private boolean flag;//定義标記,用于調節兩個線程的運作。
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内有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内有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):更改線程的優先級。
getPriority():傳回線程的優先級。
toString():傳回該線程的字元串表示形式,包括線程名稱、優先級和線程組。
Thread.yield():暫停目前正在執行的線程對象,并執行其他線程。
setDaemon(true):将該線程标記為守護線程或使用者線程。将該線程标記為守護線程或使用者線程。當正在運作的線程都是守護線程時,Java 虛拟機退出。該方法必須在啟動線程前調用。
join:臨時加入一個線程的時候可以使用join方法。當A線程執行到了B線程的join方式。A線程處于當機狀态,釋放了執行權,B開始執行。A什麼時候執行呢?隻有當B線程運作結束後,A才從當機狀态恢複運作狀态執行。
JKD1.5中提供了多線程更新解決方案。
将同步synchronized替換成顯式的Lock操作。
将Object中的wait,notify,notifyAll,替換了Condition對象。該對象可以Lock鎖擷取。
在該示例中,實作了本方隻喚醒對方的操作。
class Test implements Runnable
{
private boolean flag;//定義标記,用于調節兩個線程的運作。
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内有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内有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();
}
}
轉載于:https://blog.51cto.com/optimisticpig/1397160