實現多線程有兩種方式:(自JDK1.5之后有三種,最后一種並不常用)
1.繼承Thread類
2.實現Runnable接口(Callable接口)
一個類如果實現了Runnable接口或者繼承了Thread類,那么它就是一個多線程類,如果是要實現多線程,還需要重寫run()方法,所以run() 方法是多線程的入口。
但是在啟動多線程的時候,不是從run()方法開始的,而是從start()開始的 理由是:當執行多線程的時候,每一個線程會搶占資源,而操作系統會為其分配資源,在start()方法中不僅執行了多線程的代碼,除此還調用了一個start0()方法,該方法的聲明是native,在Java語言中用一種技術叫做JNI,即JavaNativeInterface,該技術特點是使用Java調用本機操作系統提供的函數,但是有一個缺點是不能離開特定的操作系統,如果線程需要執行,必須有操作系統去分配資源,所以此操作主要是JVM根據不同的操作系統來實現的
如果多線程是通過實現Runnable接口來實現的,那么與通過繼承Thread來實現有一個區別,那就是多線程的啟動方式——必須是通過start()來啟動,但是Runnable接口只有一個方法,並沒有start()方法,所以在啟動多線程的時候必須調用Thread類的一個構造方法——Thread(Runnable target),該構造方法得到了Runnable接口的一個實現,於是就可以調用Thread類的start()方法了。
多線程的兩種實現方式的區別:
1.Thread是Runnable接口的子類,實現Runnable接口的方式解決了Java單繼承的局限
2.Runnable接口實現多線程比繼承Thread類更加能描述數據共享的概念
注意:通過實現Runnable接口解決了Java單繼承的局限,所以不管其他的區別聯系是什么,這一點就決定了多線程最好是通過實現Runnable接口的方式
關於數據共享的簡單例子如下:
public class Thread_1 implements Runnable {
int ticket=10;
@Override public void run()
{
for (int i = 0; i < 100; i++) {
if(ticket>0){
System.out.println(ticket--);
}
}
}
public static void main(String[] args) {
/*Thread_1 thread_1=new Thread_1();
new Thread(thread_1).start();
new Thread(thread_1).start();
new Thread(thread_1).start();*/
MyThread myThread1=new MyThread();
MyThread myThread2=new MyThread();
MyThread myThread3=new MyThread();
myThread1.start();
myThread2.start();
myThread3.start();
}
} class MyThread extends Thread{
int ticket=10;
@Override public void run() {
for (int i = 0; i < 100; i++) {
if(ticket>0){
System.out.println(ticket--);
}
}
}
}
例子解析:
當通過繼承Thread類實現多線程的時候,每一個對象持有各自的10張ticket,而不是共用10張ticket,所以程序執行會重復三次,如果通過實現Runnable接口,則是三個對象共享10張ticket,實現了數據的共享。