1. 程式人生 > >Java建立執行緒的兩種方法比較

Java建立執行緒的兩種方法比較

1 前言

Java提供了執行緒類Thread來建立多執行緒的程式,執行緒類和普通java類並沒有多大差別,只是執行緒類要麼繼承了Thread類,要麼實現了Runnable介面,這也引出了實現執行緒的兩種方式:

1、A extends Thread
2、A implements Runnable

看看java API中有關Thread的介紹:
public class Thread extends Object implements Runnable
可以看出,Thread也是實現了Runnable介面

2 對比兩種執行緒的實現方式

為什麼java提供兩種方式建立執行緒,他們都有哪些區別,相比而言,那種更好呢?

在Java中,類僅支援單繼承,即每個類只能擴充套件一個外部類。也就是說,如果一個類繼承了Thread類,他將無法擴充套件其他類,即無法實現更豐富的功能,所以如果自定義類還要擴充套件其他功能,可以通過實現Runnable介面定義這個執行緒類,這樣可以避免Java單繼承帶來的侷限性。

實現Runnable介面定義執行緒類,還有一個重要功能就是可以處理同一資源,實現資源共享。

2.1 Thread實現執行緒類

兩個人分別賣100張票。

程式碼片段

public class ThreadAndRunnable {
public class sale1 extends Thread{

        private
int tikets = 100; private String saler = ""; sale1(String saler){ this.saler = saler; } public void run() { // TODO Auto-generated method stub for(int i=0;i<tikets;i++){ System.out.println(saler + " sales " + i + " tikets"
); } } } public static void main(String[] args){ sale1 saleModelOne1 = new ThreadAndRunnable().new sale1("小王"); sale1 saleModelOne2 = new ThreadAndRunnable().new sale1("小張"); saleModelOne1.start(); saleModelOne2.start(); } }

執行結果

小王 sales 0 tikets
小張 sales 0 tikets
小王 sales 1 tikets
小張 sales 1 tikets
小王 sales 2 tikets
小張 sales 2 tikets
小王 sales 3 tikets
小張 sales 3 tikets
小張 sales 4 tickets
...
小張 sales 95 tikets
小張 sales 96 tikets
小張 sales 97 tikets
小張 sales 98 tikets
小張 sales 99 tikets

通過上述結果可以看出,兩個執行緒都是獨立執行,兩者之間沒有優先順序,互不干擾。不過有人先賣完,說明CPU分配並不是均等的,有的執行緒分配多,有的分配少。

2.2 Runnable實現執行緒類

兩個人分別賣100張票。

程式碼片段

public class ThreadAndRunnable {
public class sale2 implements Runnable{

        private int tikets = 100;
        private String saler = "";

        sale2(String saler){
            this.saler = saler;
        }

        public void run() {
            // TODO Auto-generated method stub
            for(int i=0;i<tikets;i++){
                System.out.println(saler + " sales " + i + " tikets");
            }   
        }       
    }
public static void main(String[] args){

        sale2 saleModelTwo1 = new ThreadAndRunnable().new sale2("小馬");
        sale2 saleModelTwo2 = new ThreadAndRunnable().new sale2("小徐");

        Thread t1 = new Thread(saleModelTwo1);
        Thread t2 = new Thread(saleModelTwo2);
        t1.start();
        t2.start();

    }
}

執行結果

小徐 sales 0 tikets
小馬 sales 0 tikets
小徐 sales 1 tikets
小馬 sales 1 tikets
小徐 sales 2 tikets
小馬 sales 2 tikets
小徐 sales 3 tikets
小馬 sales 3 tikets
小馬 sales 4 tikets
...
小徐 sales 98 tikets
小徐 sales 99 tikets
小馬 sales 94 tikets
小馬 sales 95 tikets
小馬 sales 96 tikets
小馬 sales 97 tikets
小馬 sales 98 tikets
小馬 sales 99 tikets

通過上述結果可以看出,兩個執行緒都是獨立執行,兩者之間沒有優先順序,互不干擾。不過有人先賣完,說明CPU分配並不是均等的,有的執行緒分配多,有的分配少。

2.3 Runnable實現資源共享

三人一起賣100張票。

程式碼片段

public class ThreadAndRunnable {
public class sale3 implements Runnable{

        private int tikets = 100;

        public void run() {
            // TODO Auto-generated method stub
            while(tikets>0){
                tikets--;
                System.out.println( tikets + " tikets leave");
            }   
        }       
    }

    public static void main(String[] args){

        sale3 saleModelThree1 = new ThreadAndRunnable().new sale3();

        Thread t1 = new Thread(saleModelThree1,"小米");
        Thread t2 = new Thread(saleModelThree1,"滴滴");
        Thread t3 = new Thread(saleModelThree1,"美團");
        t1.start();
        t2.start();
        t3.start();

    }
}

執行結果

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

雖說上面這個也實現了資源共享,但僅僅是初級的共享記憶體變數,其中還是有不少問題需要處理,比如執行的次序問題,上面輸出結果因為CPU的因素,輸出不盡人意,要想實現穩定健壯的多執行緒資源共享,還需要做不少工作。可以考慮上訊息佇列。後面將會有專門文章來介紹訊息佇列。

2.4 總結

Runnable方式給我們展現了一個程式碼、資源獨立的視角,這樣執行緒、程式碼、資源三者分離,很好的體現了OOP的思想,因此,幾乎所有多執行緒都是基於Runnable實現的。