撥開雲霧見天日 —— Java多執行緒程式設計概念剖析
說到Java多執行緒程式設計,大多數人都會想到繼承Thread或實現Runnable程式設計,new 一個Thread例項,呼叫start()方法,由OS呼叫即可。具體過程如下:
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread");
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
System.out.println("執行結束!");
}
}
繼承Thread;
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("MyRunnable");
}
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
System.out.println("執行結束!");
}
}
實現Runnable;
這裡,有一個問題,就是無論繼承Thread還是實現Runnable,最後都需要有一個Thread例項,來啟用執行緒。那麼,這個例項化的Thread例項是什麼呢?僅僅代表一個執行緒。如果是這樣,那麼實現了Runnable的物件有代表什麼,它與Thread有何不同?讓我們來仔細看看Java執行緒。
Java執行緒
執行緒,就是程式中獨立執行的子任務。通常理解為輕量級程式,多個執行緒共享一個程式資源。由於執行緒是由OS分配與排程,因此容易產生資源競爭問題,所以成為整個多執行緒開發中的難點。
從對執行緒概念的理解上,可以看到,真正執行緒應該有兩個概念,(執行緒)任務和(執行緒)排程。
執行緒任務
再來看看執行緒程式碼。無論繼承Thread還是實現Runnable,都需要重寫一個run()方法,這裡面的程式碼,是執行緒執行時真正要執行的方法,也就是說,這是執行緒任務。沒任務,執行緒幹嘛?自己玩!!!肯定不可以。
從Runnable介面來看,它只有一個宣告——run,也就是說,你要為它的實現類指派任務。之所以有Runnable介面,一方面是因為Java是單繼承,不可能為了執行緒繼承了Thread還去繼承其他類,所以必須要有Runnable。第二,從物件導向設計原則——單一職責來看,一個類只負責某一方面的任務就可以了,避免引入多變數,多變數代表多不確定性,失控的機會會加大。所以需要Runnable的存在,只負責指派執行緒任務。
Thread也是存在run抽象方法的,它本身就是代表執行緒(具體哪個暫時不說)。由它例項自己然後自己啟用也是可以的,要不然,只有一個啟用而沒有任務,怎麼也說不過去。其實Thread也是實現Runnable,自己的任務還參考別人的……
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
System.out.println("執行結束!");
}
這個MyThread繼承自Thread類,並(暗藏)重寫了run()方法。沒任務玩什麼!!!
執行緒排程
有了任務,就要有人執行,就需要有排程。是誰?就是開篇問到的那個問題。兩種方式的執行緒都需要有一個Thread例項,這就是執行緒排程。
對於繼承式的執行緒,我們好理解,自己啟用自己的任務,那麼對於實現式的執行緒呢,是怎麼啟用的?
在Thread中,有一個Thread(Runnable target)構造方法,也就是說在Thread裡有一個Runnable變數。對此,Thread裡是這樣註釋的:“ What will be run.”。再看看Thread的排程程式碼:
@Override
public void run() {
if (target != null) {
target.run();
}
}
target就是Runnable例項,也就是先看看有沒有單獨的任務表(可以把Runnable看做是一個任務表),如果沒有,再檢視自己的任務。
那麼,現在就很明顯了,Thread類其實更重的職責在於執行緒排程(雖然也可以指派任務),Runnable是用來指派執行緒任務。在多執行緒程式設計中,有關競爭、安全、同步這種資源處理的問題,都發生線上程任務身上。看看同步關鍵字synchronized和Thread一點關係都沒有。如果不指定鎖,那麼預設的鎖物件就是任務例項。有關狀態、優先、通訊等,真正涉及到執行緒本身的執行,這些才是執行緒排程處理的問題。
執行緒與共享
為了進一步說明執行緒任務與執行緒排程,這裡再給出一個常見的執行緒變數共享例子:
public class MyThread extends Thread {
private int count = 5;
public MyThread(){}
/** 設定執行緒名稱 */
public MyThread(String name){
this.setName(name);
}
@Override
public void run() {
while(count>0){
count -- ;
System.out.println("由 " + this.currentThread().getName() + " 計算,count:= " +count);
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
Thread a = new Thread(thread, "A");
Thread b = new Thread(thread, "B");
Thread c = new Thread(thread, "C");
a.start();
b.start();
c.start();
}
}
執行結果如下(不同時刻執行結果不一樣):
這裡沒考慮安全問題。 可以看到,這裡三個執行緒排程器共同執行一個任務,才能實現執行緒變數共享:執行緒排程器A操作改變count值,然後執行緒排程器B接著操作改變count……
以上就是對Java執行緒程式設計概念的初步理解……
相關文章
- Java 多執行緒設計模式之基礎概念Java執行緒設計模式
- 【java】【多執行緒】程式、執行緒的基本概念(1)Java執行緒
- 好程式設計師Java學習路線分享多執行緒概念程式設計師Java執行緒
- Java多執行緒程式設計基礎Java執行緒程式設計
- Java多執行緒程式設計要點Java執行緒程式設計
- 程式設計思想之多執行緒與多程式(3):Java 中的多執行緒程式設計執行緒Java
- 好程式設計師Java教程分享Java多執行緒常見面試題程式設計師Java執行緒面試題
- 撥開雲霧見月明—計算其實很簡單
- 多執行緒程式設計執行緒程式設計
- iOS開發-多執行緒程式設計iOS執行緒程式設計
- Java 多執行緒 相關概念Java執行緒
- Java多執行緒程式設計—鎖優化Java執行緒程式設計優化
- Java-基礎程式設計-多執行緒Java程式設計執行緒
- java多執行緒程式設計--基礎篇Java執行緒程式設計
- Java多執行緒程式設計要點 (一)Java執行緒程式設計
- Java 多執行緒程式設計要點(synchronized)Java執行緒程式設計synchronized
- Java多執行緒程式設計入門(轉)Java執行緒程式設計
- 使用Java實現多執行緒程式設計Java執行緒程式設計
- 多執行緒程式設計中的幾個基本概念執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Boost多執行緒程式設計執行緒程式設計
- UNIX多執行緒程式設計執行緒程式設計
- 多執行緒程式設計(轉)執行緒程式設計
- 好程式設計師Java培訓分享Java多執行緒常見面試問題程式設計師Java執行緒面試
- java多執行緒程式設計chap5-7Java執行緒程式設計
- java多執行緒程式設計chap1-2Java執行緒程式設計
- java多執行緒程式設計chap3-4Java執行緒程式設計
- Java多執行緒程式設計之同步器Java執行緒程式設計
- Java多執行緒程式設計——進階篇一Java執行緒程式設計
- Java多執行緒程式設計——進階篇二Java執行緒程式設計
- 深入淺出Java多執行緒程式設計(轉)Java執行緒程式設計
- 淺析Java多執行緒程式設計機制Java執行緒程式設計
- .NET多執行緒程式設計(1):多工和多執行緒 (轉)執行緒程式設計
- Java多執行緒設計模式(1)Java執行緒設計模式
- java多執行緒程式設計:你真的瞭解執行緒中斷嗎?Java執行緒程式設計
- 《java學習三》併發程式設計 -------執行緒池原理剖析Java程式設計執行緒
- 好程式設計師Java培訓分享Java多執行緒程式設計師Java執行緒
- Java實驗五: Java多執行緒程式設計(頭歌)Java執行緒程式設計