在瞭解多線程之前,要先了解進程。
進程:程序的運行過程,是動態的,有就緒的狀態,執行狀態和阻塞狀態,並可以在這些中進行變遷。
線程:進程中負責執行程序的一個執行控制單位,線程負責程序的執行,而一個進程允許有多個控制單位元,我們稱爲多線程。
1.創建線程的第一種方法:
1).繼承Thread類
2).重寫Thread類裏面的run方法
3).創建線程的子類對象
4).調用start方法啓動線程
2.創建線程的第二種方法:
1).定義類實現Runnable接口
2).實現接口裏的run方法,也就是將線程執行的任務封裝在run方法中
3).創建一個線程對象然後將實現Runnable接口類作爲創建線程對象的構造方法的參數傳入
4).調用線程對象的start方法,啓動線程
線程安全:
- 多線程操作共享數據。
- 操作共享數據的代碼有多條。
解決線程完全:
- 同步代碼塊
- 好處:解決線程安全問題
- 弊端:降低了效率,每次都要判斷同步鎖
- 同步代碼塊和同步函數
- 同步代碼塊的鎖是任意對象,同步函數的鎖是this死鎖常見的情形之一,同步代碼塊的嵌套
線程創建:
繼承方式實現線程:
(1)繼承Threead類並重寫run方法
public class Talk extends Thread{
public void run() {
(2)創建線程對象並調用start方法
li.start();
public class Talk extends Thread{
private String name;
public Talk(String name){
this.name = name;
}
@Override
public void run() {
for(int i=1;i<=10;i++){
System.out.printf("to %s:%d\n",name,i);
try {
Thread.sleep((int)(Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("to %s:bye bye!\n",name);
}
}
測試:
public class Test {
public static void main(String[] args) {
Talk zhang = new Talk("zhang");
Talk li = new Talk("li");
zhang.start();
li.start();
}
}
結果:
to zhang:1
to li:1
to li:2
to zhang:2
to li:3
to zhang:3
to zhang:4
to li:4
to zhang:5
to li:5
to zhang:6
to li:6
接口方式實現線程:
- 實現Runnable接口繼承Thread類並實現run方法
public class Demo implements Runnable {
- 創建實現了Runnable接口類的實例
Talk1 zhang = new Talk1("zhang");
- 通過傳遞實例創建線程對象並調用start方法
Thread t1=new Thread("zhang");
t1.start();
線程協作:
wait:使當前線程進入阻塞狀態,相當於P操作;
notify:喚醒此同步鎖上阻塞的第一個線程,相當於V操作;
notifyAll:喚醒此同步鎖上阻塞的所有個線程。