Thread,Runnable的區別
我們創建線程的方式一般來說有兩種,首先我們來看看兩種啓動線程方式的具體實現。
- 第一種繼承Thread類,實現run方法,最後調用start方法啓動線程。
- 第二種實現Runnable接口,實現run方法,然後調用Thread的有參構造方法,將Runnable的子類對象作爲構造方法的參數創建一個Thread對象,最後調用start方法啓動線程。
從上面兩點來看就能知道這兩種方式的不同了。
- 首先,第一點,Thread是類,而Runnable是接口。java中不能同時繼承多個類,但是可以實現多個接口。所以相對Runnable來說,Thread方式在抽象開發上來說就侷限了一點。
- 其次是第二點,Runnable實現線程的方式需要將Runnable子類對象作爲Thread有參構造方法的參數傳入,也就是說我們創建多個Thread對象,但是可以用同一個Runnable子類對象作爲構造方法參數傳入,這樣多個線程訪問的就是同一個對象的數據和運行同樣的代碼(也即是同一個任務)。而Thread要直接做到這一點就不行,當然了我說的是直接做到不行,通過其他方式中轉一下也是可以的(比如說:用靜態變量或者新建一個數據類對象傳入就可以達到訪問同一個變量),只不過這樣就相對麻煩了一些哈!
Thread線程實現
線程類:
package com.example; /** * Created by PICO-USER on 2017/11/8. */ public class MyThread extends Thread { private int number = 5; @Override public void run() { super.run(); synchronized (this) { for (int i = 0; i < 6; i++) { synchronized (MyThread.class) { if (number > 0) { System.out.print(getName() + " number = " + number + "\n"); number--; } } } } } }
主程序入口:
public class MyClass { public static void main(String[] args0) throws InterruptedException { Thread thread = null; for (int i = 0; i < 3; i++) { thread = new MyThread(); thread.setName("Thread_" + i); thread.start(); } } }輸出結果:
看看上面的結果,我們用的是非靜態變量,所以三個線程操作的是三個不同的對象的數據。但是Runnable方式的就不醬紫了(看下面)。
Runnable線程實現
package com.example; /** * Created by PICO-USER on 2017/11/8. */ public class MyRunnable implements Runnable { public int number = 5; @Override public void run() { String name = Thread.currentThread().getName(); synchronized (this) { for (int i = 0; i < 6; i++) { if (number > 0) { System.out.print(name + " number = " + number + "\n"); number--; } } } } }
主程序入口:
package com.example; import java.util.Properties; public class MyClass { public static void main(String[] args0) throws InterruptedException { Runnable runnable = new MyRunnable(); Thread thread = null; for (int i = 0; i < 3; i++) { thread = new Thread(runnable); thread.start(); } } }輸出結果:
總結:很明顯,同樣的任務,輸出的結果卻是不一樣的。其實說到底,將線程跟類這兩個概念分開理解清楚,一切問題也就迎刃而解了。啓動線程是去執行任務,任務是run方法中的代碼執行,那具體操作的數據,是類中的數據。Thread方式,啓動線程的是Thread,操作的數據和執行的任務還是在Thread的子類,而Runnable方式中,啓動線程的是Thread類,而操作的數據和執行的任務卻是在Runnable子類中。