Java併發編程(Java Concurrency)(7)- 創建並啓動 Java 線程

原文鏈接:http://tutorials.jenkov.com/java-concurrency/creating-and-starting-threads.html

摘要:這是翻譯自一個大概30個小節的關於Java併發編程的入門級教程,原作者Jakob Jenkov,譯者Zhenning Lang,轉載請註明出處,thanks and have a good time here~~~(希望自己不要留坑)

Java 線程如 Java 中其他對象一樣也是一個對象。線程是 java.lang.Thread 的實例,或者是其子類的實例,Java 線程用來執行代碼。

1 Java 線程視頻教程

下面的鏈接是一個 Java 線程的視頻教程
https://www.youtube.com/embed/9y7l6QHpoQI

2 創建並啓動線程

Java 中像這樣創建一個線程:

Thread thread = new Thread();

爲了使這個線程啓動,需要調用其 start() 方法,

thread.start();

上面的例子沒有指定這個線程需要執行的代碼,所以這個線程將在啓動後立刻結束。

有兩種方法來指定線程需要執行的代碼。第一種是創建 Thread 的子類並覆蓋其 run() 方法,第二種方法是向 Thread 的構造函數傳遞一個實現了 Runnable(java.lang.Runnable) 接口的對象,下面將分別予以介紹。

2.1 創建Thread 的子類

第一種指定線程執行代碼的方法是創建一個 Thread 類的子類並覆蓋其 run() 方法,run() 的內部的代碼就是調用 start() 後所執行的代碼,如下例所示:

public class MyThread extends Thread {
    public void run(){
        System.out.println("MyThread running");
    }
}

創建並啓動上面線程的代碼如下:

MyThread myThread = new MyThread();
myTread.start();

start() 函數被調用後,當線程開始將立刻返回,而不會等到 run() 中的代碼被執行完畢。run() 方法將在新線程中被執行,就好像在一個獨立的 CPU 中。上例中 run() 方法將打印“MyThread running”。

也可以使用匿名內部類來實現上面的內容:

Thread thread = new Thread(){
    public void run(){
        System.out.println("Thread Running");
    }
}
thread.start();

2.2 實現 Runnable 接口

第二種指定多線程執行代碼的方法是創建一個實現 java.lang.Runnable 接口的類。Runnable 對象可以被線程執行。下面是一個簡單示例:

public class MyRunnable implements Runnable {
    public void run(){
       System.out.println("MyRunnable running");
    }
}

爲了讓 run() 方法中的代碼被線程執行,需要將 MyRunnable 類的實例傳給 Thread 的構造函數,如下所示:

Thread thread = new Thread(new MyRunnable());
thread.start();

當 thread 啓動時,它會調用 MyRunnable 類的實例的 run() 方法,而不是其自己的 run() 反覆。上例會打印“MyRunnable running”。

也可以以匿名內部類的方式實現 Runnable 接口,如下所示:

Runnable myRunnable = new Runnable(){
    public void run(){
        System.out.println("Runnable running");
    }
}
Thread thread = new Thread(myRunnable);
thread.start();

3 常見錯誤:錯把 run() 方法當做 start() 方法

當創建和啓動新線程時一個常見的錯誤是調用 run() 方法來啓動線程,而沒有調用 start() 方法,如下:

Thread newThread = new Thread(MyRunnable());
newThread.run();  //should be start();

雖然一開始一切看起來都很正常,運行結果也符合你的預期,但代碼並沒有在新線程中執行,而是在創建新線程的線程中被執行了。換言之就是沒有創建新的線程。

4 線程名

當你創建一個 Java 線程時你可以給其取一個名字,用於幫助你區分不同的線程。舉例來說,如果多個線程都調用 System.out,那麼很難判斷究竟是哪個線程進行了輸出。下面是給線程指定名稱的例子:

Thread thread = new Thread("New Thread") {
    public void run(){
        System.out.println("run by: " + getName());
    }
};
thread.start();
System.out.println(thread.getName());

上面傳給 Thread 構造函數的字符串“New Thread”就是線程的名字。這個名字可以通過 Thread 類的 getName() 方法來獲得。實現 Runnable 接口的方式下給線程賦名字的示例如下:

MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable, "New Thread");
thread.start();
System.out.println(thread.getName());

這裏需要注意的是,由於 MyRunnable 類並不是 Thread 的子類,所以 MyRunnable 類內的 run() 方法並不能調用 getName() 方法(當然,可以通過 Thread.currentThread().getName() 實現這個功能)。

5 Thread.currentThread()

Thread.currentThread() 方法返回執行 Thread.currentThread() 函數的線程的實例引用。通過這種方法可以在代碼中獲得當前線程的 Thread 對象,如下例所示:

Thread thread = Thread.currentThread();

一旦獲得了 Thread 對象的引用,就可以調用其中的方法。下例展示瞭如何獲得當前線程的名稱:

String threadName = Thread.currentThread().getName();

6 實例

下面是一個實例。首先打印出 main() 方法所在線程的線程名稱(該線程名稱由 JVM 分配);然後啓動 10 個線程,並且給每個線程賦一個名字,其格式是 “” + i;每個線程的工作是輸出自己的線程名,然後停止:

public class ThreadExample {
    public static void main(String[] args){
        System.out.println(Thread.currentThread().getName());
            for(int i=0; i<10; i++){
                new Thread("" + i){
                    public void run(){
                        System.out.println("Thread: " + getName() + " running");
                    }
                }.start();
            }
        }
    }

注意到雖然每個線程都是按照 1,2,3, … 的順序被創建和啓動的,但其執行順序卻可能不是這個順序。例如線程 1 可能不是第一個執行輸出的線程。這是因爲本質上這些線程是並行而非順序執行的。JVM 和/或者操作系統將決定線程的執行順序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章