什麼是線程?
答:是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位---------------------->個人認爲是在一個程序中(進程)的一個獨立,而且可以多個並行執行的一條執行路徑。
什麼是進程?
答:進程是由多個線程實例組成的一組線程的集合,它可以看出是一個程序運行的實例
線程和進程的區別?
答:到了這裏應該很明確了,線程是一組線程的一個集合,線程是一個進程中的一個獨立的可以並行執行的一個執行路徑。
回到我們的主題:多線程
顧名思義,多線程就是很多個線程,那麼線程的特點是什麼,可以並行執行,而且是一條獨立的執行路徑。
那麼我們可以看出多線程的優點:提高程序的執行效率,如果還不理解,那麼我們就舉個栗子:
通過上面的圖,我們可以很清晰的看到,貨物a之後一個卡車在拉貨,完成任務需要五個小時,但是貨物b是三個卡車在拉貨,而且每個卡車都有屬於自己的道路,也就不會存在堵車的情況,那麼效率會相對於貨物a大大提高。那麼多線程的優點久跟這個原理一樣。可以提高程序執行效率。
那麼多線程真的是同時在進行執行嗎?其實多線程不是在同時執行的,多線程會進行對CPU的搶渡,多個線程在就緒狀態之後,CPU會進行隨機分配資源,那個線程拿到資源就可以進行執行,當然這是非常非常短暫的一個時間,我們幾乎是可能感覺得到得,所以才說是在並行進行執行,而且是獨立的,也就是說線程與線程之間是互不影響的,
總結:就是線程是CPU隨機進行分配資源,拿到資源的纔可以進行運行,但是時間是非常短的,所以對於我們可以說是同時進行執行的,其次,就是線程是獨立的,互不影響的。
凡事都是物極必反的,多線程同樣如此,就拿上圖來說把,雖然我們這裏使用了三個卡車進行執行,效率變快了,但是也需要老闆有哪個實力啊,如果你沒有那麼多錢,還叫那麼多卡車,最後會導致什麼結果,多線程也是如此,就算線程能提高程序執行效率,但是也不能盲目的使用,要根據自己的硬件也就是CPU進行合理分配纔行。
多線程使用場景:執行比較耗時,但是又不希望影響到主線程的東西,比如下載,數據庫連接池等
好了下面我們就開始在java中使用多線程
首先我們得了解一下如何創建一個多線程,多線程的創建方式有很多,這裏列舉三個:
1:繼承Thread類
class CreateThread extends Thread {
// run方法中編寫 多線程需要執行的代碼
publicvoid run() {
for (inti = 0; i< 10; i++) {
System.out.println("i:" + i);
}
}
}
publicclass ThreadDemo {
publicstaticvoid main(String[] args) {
System.out.println("-----多線程創建開始-----");
// 1.創建一個線程
CreateThread createThread = new CreateThread();
// 2.開始執行線程 注意 開啓線程不是調用run方法,而是start方法
System.out.println("-----多線程創建啓動-----");
createThread.start();
System.out.println("-----多線程創建結束-----");
}
}
那麼執行結果爲:
爲什麼出現這種情況:那是因爲線程是獨立的一條執行路徑,上面的代碼中存在兩個線程,其中main方法是主線程,我們自定義的類是子線程,由於主線程之中的東西非常少,所以在我們子線程還沒有執行完畢我們的主線程就執行完畢了,所以纔會有這樣的結果。
2:實現Runnable接口
class CreateRunnable implements Runnable {
@Override
publicvoid run() {
for (inti = 0; i< 10; i++) {
System.out.println("i:" + i);
}
}
}
publicclass ThreadDemo2 {
publicstaticvoid main(String[] args) {
System.out.println("-----多線程創建開始-----");
// 1.創建一個線程
CreateRunnable createThread = new CreateRunnable();
// 2.開始執行線程 注意 開啓線程不是調用run方法,而是start方法
System.out.println("-----多線程創建啓動-----");
Thread thread = new Thread(createThread);
thread.start();
System.out.println("-----多線程創建結束-----");
}
}
這上面的運行結果跟繼承thread類的差不多,同理
3:匿名內部類方式
public class CreateThread {
public static void main(String[] args) {
System.out.println("主線程開始執行");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子線程開始執行");
for (int i = 0 ; i < 10 ; i++){
System.out.println("i:"+i);
}
System.out.println("子線程執行結束");
}
});
thread.start();
System.out.println("主線程執行完畢");
}
}
執行結果,同理
----多線程推薦事項繼承Runnable接口,我們還是要面向接口編程哈
另外啓動多線程是thread.start(),很多初學的小夥伴會認爲是thread.run(),run()方法只是人家多線程執行的一個入口,我們需要使用多線程執行的東西就是放在run方法裏面的,但是啓動多線程還是使用thread.start()
我們創建了多線程,並且可以輸出打印一段話了,那麼多線程的執行流程是如何的,那就要說到我們線程的五個狀態,創建,就緒,運行,阻塞,銷燬
創建:就是我麼創建了一個Thread的實例,但是沒有做任何操作
就緒:即是我們調用thread.start()方法,因爲前面也說了,線程的運行是拿到CPU的資源之後纔會執行,沒拿到就會進行等待,所以說調用thread.start()是就緒狀態,因爲這之間的時間是非常短暫的,所以往往調用了thread.start()就會執行,讓人誤以爲thread.start()就是啓動線程
運行:這個時候線程拿到了CPU的資源,進行執行run方法了
阻塞:這種情況就是線程在一些情況下停止了繼續往後面執行,比如等待別的真正使用的鎖,使用sleep方法,等很多
銷燬:當線程發生未捕獲的錯誤,或者正常執行完畢之後,線程就會進行銷燬
常用線程api方法 |
|
start() |
啓動線程 |
currentThread() |
獲取當前線程對象 |
getID() |
獲取當前線程ID Thread-編號 該編號從0開始 |
getName() |
獲取當前線程名稱 |
sleep(long mill) |
休眠線程 |
Stop() |
停止線程, |
isAlive() |
如果線程是正在允許或者被阻塞返回true,如果是沒有就緒或者死亡的線程返回false |
Join() |
可以讓一個線程優先執行 |
setPriority() |
設置線程的優先級,也就是獲取CPU的可能性會更大,但是可能看不出效果,可以傳遞0~10 |
常用線程構造函數 |
|
Thread() |
分配一個新的 Thread 對象 |
Thread(String name) |
分配一個新的 Thread對象,具有指定的 name正如其名。 |
Thread(Runable r) |
分配一個新的 Thread對象 |
Thread(Runable r, String name) |
分配一個新的 Thread對象 |
另外可以使用idea工具點擊進入Thread類,可以看到更多。