1. 程式人生 > >多執行緒基礎知識(一) 執行緒的概念及建立任務與執行緒

多執行緒基礎知識(一) 執行緒的概念及建立任務與執行緒

執行緒的概念及建立任務與執行緒

引言

多執行緒使得程式中的多個任務可以同時執行。

java的重要功能之一就是內部支援多執行緒————在一個程式中運行同時執行多個任務。在許多程式設計語言中,多執行緒都是通過呼叫依賴於系統的過程或函式來實現的。在本文中,將介紹執行緒的該奶奶及如何在Java中執行一個多執行緒的例子。

一、執行緒的概念

概念

首先,何謂執行緒? 一個程式可能包含多個可以同時執行的任務,執行緒是指一個任務從頭至尾的執行流程。

執行緒提供了執行一個任務的機制,對於Java而言,可以在一個程式中併發地啟動多個執行緒,這些執行緒可以在多處理器系統上同時執行。若只有一個處理器,則多個執行緒共享單個CPU。

在單處理器系統中,多個執行緒共享CPU時間成為時間分享,而作業系統負責排程及分配資源給它們。這種安排之所以是可行的,是因為CPU的大部分時間都是空閒的。例如,在等待使用者輸入資料時,CPU什麼都不做。

多執行緒可以使程式反應更快、互動性更強、執行效率更高,例如,一個好的文書處理程式允許在輸入文字的同時列印或者儲存檔案。在一些情況下,即使是在單處理器系統上,多執行緒程式的執行速度也比單執行緒程式更快。Java對多執行緒程式的建立和執行,以及鎖定資源以避免衝突提供了非常好的支援。

Java中的執行緒

可以在程式中建立附加的執行緒以執行併發任務在Java中,每個任務都是Runnable

介面的一個例項,也稱為可執行物件(runnable object)

Java中,從本質上來講,執行緒就是一個便於任務執行的物件

二、如何建立任務與執行緒

如上一小節中所講,任務就是物件。為了建立任務,必須首先為這個任務定義一個實現Runnable介面的類(否則如何建立這個例項呢?)。Runnable介面非常簡單,它只包含一個run方法,因此只要我們建立的類中也包含這個方法即可。而這個方法的作用就是告訴系統執行緒將如何執行的。如我們可以如以下的形式定義一個實現某任務的類:

public class TaskClass implements runnable {
  public
TaskClass(...) {} @Override public void run() }

人任務必須線上程中執行,Thread類包括建立執行緒的構造方法以及控制執行緒的很多有用的方法,如對於上面的TaskClass類,可以使用如下的語句為其建立任務的執行緒:

  TaskClass task = new TaskClass(...);  // 先建立一個任務的例項
  Thread thread = new Thread(task);     // 將可執行物件傳入

然後呼叫start()方法告訴Java虛擬機器該執行緒準備執行:

  thread.start()

之後,Java虛擬機器通過呼叫任務的run()方法執行任務。

在下面的例子中,會建立3個任務以及3個執行這些任務的執行緒,其中:

  • 任務1 列印字母 ‘a’ 100次
  • 任務2 列印從1到100的整數

首先,是建立兩個分別實現這兩個任務的類:

// PrintChar.java

package learning_java.book.concurrency;

public class PrintChar implements Runnable {
    private char charToPrint;
    private int times;

    public PrintChar(char c, int t) {
        charToPrint = c;
        times = t;
    }

    @Override
    public void run() {
        for (int i = 0; i < times; i ++) {
            System.out.print(charToPrint);
        }
    }
}
// PrintNum.java

package learning_java.book.concurrency;

public class PrintNum implements Runnable{
    private int lastNum;

    public PrintNum(int n) {
        lastNum = n;
    }

    public void run() {
        for (int i = 1; i <= lastNum; i ++) {
            System.out.print(" " + i);
        }
    }

    public static void main(String[] args) {
        new PrintNum(10).run();
    }
}

之後,再建立一個主方法的類,建立這兩個任務的例項,併為其建立執行緒並執行。

//TaskThreadDemo.java

package learning_java.book.concurrency;

public class TaskThreadDemo {
    public static void main(String[] args) {
        Runnable printA = new PrintChar('a', 100);
        Runnable print100 = new PrintNum(100);

        Thread thread1 = new Thread(printA);
        Thread thread2 = new Thread(print100);

        thread1.start();
        thread2.start();
    }
}

輸出:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1aaaaaaaaaaa 2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3a 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

在這短程式中,若從結果看不到併發執行三個執行緒的效果,那麼就要增加列印字元與數字的個數,如更改為列印1000次。

最後,還有一點需要注意的是,在任務類中的run()方法知名如何完成這個任務,如果使用Thread類的方法為其構建執行緒並執行的話,Java虛擬機器會自動呼叫該方法,而無需特意呼叫它。如果手動在程式碼中呼叫一個例項的run()方法,則效果只是在同一個執行緒中執行該方法,而不是有新執行緒被啟動。