多線程可以通過兩種方式來創建:
一、通過繼承Thread類。
二、通過實現Runnable接口。
那么中兩種方式到底有什么區別呢?那種方式更好些呢?
先看看幾個簡單的Demo:
Demo1
public class MyThread { public static void main(String[] args) { ThreadTest t = new ThreadTest(); t.start(); t.start(); t.start(); t.start(); } } class ThreadTest extends Thread { private int n = 10; @Override public void run() { while (n > 0) { System.out.println(Thread.currentThread().getName() + " " + n--); } } }
運行后可以看出,其實只啟動了一個線程,而且還拋異常了,這個在下面說。
我們修改一下代碼:
Demo2
public class MyThread { public static void main(String[] args) { new ThreadTest().start(); new ThreadTest().start(); new ThreadTest().start(); new ThreadTest().start(); } } class ThreadTest extends Thread { private int n = 10; @Override public void run() { while (n > 0) { System.out.println(Thread.currentThread().getName() + " " + n--); } } }
再次運行,發現這四個線程對象各自占有各自的資源,並不是同時完成統一任務。
我們可以得出結論:Thread類實際上無法達到資源共享的目的。
那么,Runnable接口能不能達到這一目的呢?
Demo3
public class MyThread { public static void main(String[] args) { RunnableTest r = new RunnableTest(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); } }class RunnableTest implements Runnable { private int n = 10; @Override public void run() { while (n > 0) { System.out.println(Thread.currentThread().getName() + " " + n--); } } }
運行后我們發現,這四個線程同時完成了統一的任務,可以達到資源共享的目的
通過以上比較我們即可得出Thread與Runnable的區別:
1、Runnable適合於多個相同程序代碼線程去處理統一資源的情況,把虛擬的cpu(線程)同程序的代碼,數據有效分離,較好體現面向對象的編程的思想
2、Runnable可以避免由於java的單繼承機制帶來的局限。可以再繼承其他類的同時,還能實現多線程的功能。
3、Runnable能增加程序的健壯性。代碼能夠被多個線程共享。
我們把Demo1的線程start()方法改成run()試試
public class MyThread { public static void main(String[] args) { ThreadTest t = new ThreadTest(); t.run(); t.run(); t.run(); t.run(); } } class ThreadTest extends Thread { private int n = 10; @Override public void run() { while (n > 0) { System.out.println(Thread.currentThread().getName() + " " + n--); } } }
運行后結果:
把Demo2的所有線程的start方法改成run試試
public class MyThread { public static void main(String[] args) { new ThreadTest().run(); new ThreadTest().run(); new ThreadTest().run(); new ThreadTest().run(); } } class ThreadTest extends Thread { private int n = 10; @Override public void run() { while (n > 0) { System.out.println(Thread.currentThread().getName() + " " + n--); } } }
運行后結果:
由此我們可以區別:
1、start()方法:啟動一個線程,不能多次啟動一個線程。
2、run()方法:在本線程內調用run()方法,可以重復多次調用。
3、用start()方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。
4、run()方法只是類的一個普通方法而已,如果直接調用Run方法,程序中依然只有主線程這一個線程,其程序執行路徑還是只有一條,還是要順序執行,要等待run方法體執行完畢后才可繼續執行下面的代碼。