1. 程式人生 > >(十)java併發程式設計--建立和啟動執行緒(java.lang.Thread 、java.lang.Runnable)

(十)java併發程式設計--建立和啟動執行緒(java.lang.Thread 、java.lang.Runnable)

執行緒建立的幾種方式.

建立和啟動一個執行緒

建立一個執行緒.

Thread thread = new Thread();

啟動java執行緒.

thread.start();

這兩個例子並沒有執行執行緒執行體,執行緒將會啟動後然後立即停止。
有兩種方式可以指定執行緒要執行的執行緒體。
1 、建立Thread的子類並且重寫run()方法。
2、一個物件實現Runnable介面。

執行緒的子類實現方式

第一種方式執行執行緒執行一些程式碼,是建立執行緒的子類,並且重寫Thread父類的方法run()方法。run()方法在我們呼叫start()方法後將會被執行。
如下程式碼:

package thread_create;

/**
 * Created by fang on 2017/12/1.
 * 執行緒建立的第一種方式,繼承Thread類,並實現run()方法.
 */
public class MyThread extends Thread{

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

}

建立和啟動執行緒上面的執行緒體。

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


start() 方法呼叫將會立刻返回只要執行緒啟動了。它不會等待run()方法執行完成,run()方法可能將被不同的cup執行。當run() 方法執行後會打印出“MyThread running”。

我們也可以使用匿名子類,如下程式碼。

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

        thread.start();

Runnable 介面實現方式

第二種方式執行執行緒的程式碼可以建立一個類實現java.lang.Runnable。Runnable的子類物件能夠被一個執行緒執行。
example:

package thread_create;

/**
 * Created by fang on 2017/12/1.
 * 第二種方式實現Runable介面
 */
public class MyRunnable implements Runnable{

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

run() 方法將被一個執行緒執行,傳遞例項物件MyRunnable 給一個執行緒的構造方法,如下程式碼.

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

執行緒開始將會呼叫run()方法,MyRunnable()例項將會替代Thread自己的run()方法,會打印出”MyRunnable running”.

我們可以可以使用匿名類實現介面.

 // 匿名類實現介面.
        Runnable myRunnable = new Runnable() {
            public void run() {
                System.out.println("Runnable running");
            }
        };
        Thread thread1 = new Thread(myRunnable);
        thread1.start();

繼承還是使用Runnable?

Runnable和Thread關係圖如下:
這裡寫圖片描述
沒有規定那個最好,這兩種方式都可以。個人認為,我更喜歡使用Runnable,Thread將會獲得實現Runnable介面的例項。當我們使用執行緒池的時候,很容易將
Runnable例項排好隊,直到池中空閒。但對於執行緒子類來說有些困難。

通常的陷阱:呼叫run()方法替代start()

當我們建立和開始一個執行緒的時候可能直接呼叫run()方法替代呼叫start()方法,如下。
Thread newThread = new Thread(myRunnable);
newTherad.run();

執行的時候我們可能發現run()方法執行的和我們期望的一樣,但是它並不是我們自己啟動的執行緒執行的,而是由執行上述兩行程式碼的執行緒執行的,例如可以能是在main()主執行緒中執行的。如果我們想要使用我們newThread所呼叫的Runnable中的run()方法,必須使用newThead.run();

執行緒的名字

當你建立一個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());

使用Runnable方式也可以傳遞執行緒的名字.如下程式碼

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

MyRunnable 類不是Thread的子類,它不能訪問執行它執行緒的getName()方法.

Thread.currentThread()

currentThread()方法返回正在執行currnetThread()執行緒的例項引用。通過這種方式,可以訪問java的執行緒物件,該物件表示執行給定程式碼塊的執行緒。
如下例項

    String threadName = Thread.currentThread().getName();
    System.out.println("當前執行緒名稱" +threadName);

java 執行緒例子

package thread_create;

/**
 * Created by fang on 2017/12/1.
 */
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();
        }
    }
}

執行結果:

main
Thread: 0 running
Thread: 1 running
Thread: 2 running
Thread: 4 running
Thread: 3 running
Thread: 6 running
Thread: 5 running
Thread: 7 running
Thread: 9 running
Thread: 8 running

Process finished with exit code 0

即使執行緒按照順序啟動的(start()),但是它們可能不會按照順序執行,這意味著執行緒1可能不是第一個將其名稱寫入System.out的執行緒,這是因為執行緒在原則上是並行執行的,而不是按照順序執行的。JVM和作業系統決定了執行緒的執行順序,這個順序不必是它們開始的順序。所以可能會輸出如上結果。

執行緒宣告異常和執行緒體的返回值?Callable、Future使用

上述兩種方式線上程執行體run()方法上並沒有執行緒的返回值,以及可以對外宣告異常.
Java 5引入了Java.util.concurrent。併發包中的可呼叫介面,它類似於Runnable介面,但它可以返回任何物件,並能夠丟擲異常。
這篇有些長,下一篇使用Callable 和Future完成攜帶返回值的執行緒建立.