Java多線程學習(一)

創建一個線程主要有兩個方法:實現Runnable接口和繼承Thread類。雖然Thread類底層也實現了Runnable接口,但在使用的時候兩者還是有很大差別。

1. 繼承Runnable接口:

public class TestRunnable implements Runnable{
    private String name;    //給線程一個名稱,方便標識

     public TestRunnable(String name){
        this.name = name;
    }

    @Override
    public void run(){
        for(int i=0; i<10; i++){
            System.out.println(name+"正在運行:"+"   "+i);
        }
    }

    public static void main(String[] args){
        TestRunnable t1 = new TestRunnable("A");
        TestRunnable t2 = new TestRunnable("B");

        Thread thread1 = new Thread(t1);    //用實現Runna接口的對象來創建線程
          Thread thread2 = new Thread(t2);

        thread1.start();
        thread2.start();
    }
}
運行結果爲:

A正在運行:   0
B正在運行:   0
A正在運行:   1
B正在運行:   1
A正在運行:   2
B正在運行:   2
A正在運行:   3
A正在運行:   4
B正在運行:   3
A正在運行:   5
B正在運行:   4
A正在運行:   6
B正在運行:   5
A正在運行:   7
B正在運行:   6
A正在運行:   8
B正在運行:   7
A正在運行:   9
B正在運行:   8
B正在運行:   9

再運行一次,發現結果不一樣:

A正在運行:   0
B正在運行:   0
A正在運行:   1
B正在運行:   1
A正在運行:   2
B正在運行:   2
A正在運行:   3
A正在運行:   4
A正在運行:   5
A正在運行:   6
A正在運行:   7
A正在運行:   8
A正在運行:   9
B正在運行:   3
B正在運行:   4
B正在運行:   5
B正在運行:   6
B正在運行:   7
B正在運行:   8
B正在運行:   9

這是因爲每次在運行中,線程都要搶奪CPU資源,由於優先級不同,最終執行的順序和結果也不同。

2. 繼承Thread類:

public class TestThread extends Thread{
    private String name;

    public TestThread(String name) {
        this.name = name;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(name + "正在運行   " + i);
        }
    }

    public static void main(String[] args) {
        TestThread h1 = new TestThread("A");
        TestThread h2 = new TestThread("B");
        h1.start();
        h2.start();
    }
}
運行結果:

A正在運行   0
B正在運行   0
A正在運行   1
B正在運行   1
A正在運行   2
B正在運行   2
A正在運行   3
B正在運行   3
A正在運行   4
B正在運行   4
A正在運行   5
B正在運行   5
A正在運行   6
B正在運行   6
A正在運行   7
B正在運行   7
A正在運行   8
A正在運行   9
B正在運行   8
B正在運行   9

3. Thread與Runnable比較:

看上去Thread的寫法更簡潔,只需要創建對象並start就好。如果不使用公共資源,確實用Thread更方便。但如果有一個變量是多個線程間共享的,怎麼辦?

在TestThread對象中增加一個字段count。

public class TestThread extends Thread{
    private String name;
    private int count = 10;

    public TestThread(String name) {
        this.name = name;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            --count;
            System.out.println(name + "正在運行   " + i + "   count還有"+count);
        }
    }

    public static void main(String[] args) {
        TestThread h1 = new TestThread("A");
        TestThread h2 = new TestThread("B");
        h1.start();
        h2.start();
    }
}
結果怎樣可以猜出來,這根本是兩個對象,各計算各的。

A正在運行   0   count還有9
B正在運行   0   count還有9
B正在運行   1   count還有8
B正在運行   2   count還有7
B正在運行   3   count還有6
B正在運行   4   count還有5
B正在運行   5   count還有4
B正在運行   6   count還有3
B正在運行   7   count還有2
B正在運行   8   count還有1
A正在運行   1   count還有8
B正在運行   9   count還有0
A正在運行   2   count還有7
A正在運行   3   count還有6
A正在運行   4   count還有5
A正在運行   5   count還有4
A正在運行   6   count還有3
A正在運行   7   count還有2
A正在運行   8   count還有1
A正在運行   9   count還有0

那如果換成static類型的變量呢?static爲類的所有對象維護一個公共變量。

A正在運行   0   count還有9
B正在運行   0   count還有8
A正在運行   1   count還有7
B正在運行   1   count還有6
A正在運行   2   count還有5
B正在運行   2   count還有4
A正在運行   3   count還有3
B正在運行   3   count還有2
B正在運行   4   count還有0
B正在運行   5   count還有-1
B正在運行   6   count還有-2
B正在運行   7   count還有-3
B正在運行   8   count還有-4
B正在運行   9   count還有-5
A正在運行   4   count還有1
A正在運行   5   count還有-6
A正在運行   6   count還有-7
A正在運行   7   count還有-8
A正在運行   8   count還有-9
A正在運行   9   count還有-10

乍一看似乎不錯,但如果仔細觀察,會發現順序和數字根本不對。所以用Thread不能正確的實現資源共享。




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