Java實現多線程所有方法都要通過Tread類實現,Thread類中的Start0()方法使用JNI(Java Native Interface)來和操作系統交互,進行線程計算。
有三種方法實現Java多線程編程:
- 繼承Thread類,在子類中重寫Thread類的run()方法。
- 實現Runnable接口,在實現接口的類中實現方法run()。
- 用類A實現callable接口,再用A的對象初始化一個FutureTask對象B,FutureTask實現的是RunnalbleTask接口,RunnalbleTask繼承了Runnalble接口以及的Future類,因此可以用對象B初始化一個Thread對象。
第一種:繼承Thread類
Thread類中有run()方法,run()中爲多線程中的資源代碼,也就是線程中要執行的代碼(此時先不管run()方法重寫前是是什麼內容)。
Thread類中的start()方法中調用了start0()方法,這個方法是在Thread類被創建的時候,在靜態塊中使用registerNatives()創建的本地方法。在本地方法start0()中最終會實現run()方法中的代碼,實現本地線程運行run()中的代碼。
demo代碼爲:
import java.lang.Thread;
public class ThreadsDemo extends Thread {
String title="";
ThreadsDemo(String title){
this.title=title;
}
@Override
public void run(){
for(int i=0;i<10;i++) {
System.out.print(this.title);
}
}
public static void main(String[] args){
ThreadsDemo threadA = new ThreadsDemo("a");
ThreadsDemo threadB = new ThreadsDemo("b");
ThreadsDemo threadC = new ThreadsDemo("c");
threadA.start();
threadB.start();
threadC.start();
}
}
第二種:實現Runnable接口
我們知道在第一種方法中通過重寫Thread的run()方法來寫入我們的業務代碼,其實Thread中run()方法本來實現的是一個Runnable接口實現類中的run()方法。Thread的構造函數中可以使用Runnable接口的實現類初始化。因此我們可以使用Runnable實現類來初始化Thread對象。然後再使用Thread中的start()啓動線程,後續動作就和上面的一樣了。
優點:相比第一種,實現Runnable接口可以避免受困於多繼承的侷限。
import java.lang.Runnable;
public class RunnableDemo implements Runnable{
public int a = 0;
public synchronized void run(){
for(int i=0;i<100000000;i++) {
this.a = a + 1;
//System.out.println(a);
}
System.out.println(a);
}
public static void main(String[] args) throws Exception{
RunnableDemo rd = new RunnableDemo();
Thread ta = new Thread(rd);
Thread tb = new Thread(rd);
ta.setPriority(10);
ta.start();
//ta.join();
tb.start();
//tb.join();
System.out.println("wed"+rd.a);
}
}
第三種:實現callable接口
callable接口中的call方法可以有返回值。使用FutureTask的get方法獲取。
Callable接口所在的包爲JUC(java.util.concurrent),實現Callable同樣最終要通過Thread類實現多線程。
callable對象作爲參數 初始化FutureTask類,FutureTask類實現了RunnableFuture接口,
RunnableFuture接口繼承了Runnable和Future接口,其中繼承Runnable可以使RunnableFuture接口可以像Runnable一樣初始化Thread類,Future接口提供了get方法,用來獲取Callable中call()方法的返回值。
import java.util.concurrent.Callable;
import java.lang.String;
import java.util.concurrent.FutureTask;
public class CallableDemo implements Callable<Integer> {
public Integer call() throws Exception{
int re=0;
for(int i=0;i<10;i++){
System.out.println(i);
re++;
}
return re;
}
public static void main(String[] args) throws Exception{
CallableDemo cd = new CallableDemo();
FutureTask<Integer> ft = new FutureTask(cd);
Thread ta = new Thread(ft);
ta.start();
int a = ft.get();
System.out.println(a);
}
}