有3種實現方法,繼承Thread類、實現Runnable接口、通過Callable接口實現多線程
1.1 繼承Thread類
步驟:
1)繼承Thread 類
2)重寫父類run 方法
3)在run方法編寫線程需求做的代碼塊
4)實例化線程類
5)調用線程start(啟動線程)
public class ThreadDemo extends Thread{ /** * 1.繼承Thread類 * 2.重寫run()方法 */ @Override public void run() { System.out.println("我來了!~~~~~~"); } public static void main(String[] args) { ThreadDemo thread1 = new ThreadDemo(); ThreadDemo thread2 = new ThreadDemo(); thread1.start();//啟動線程
thread2.start();//啟動線程 //啟動線程的唯一方法就是通過Thread類的start()實例方法。 //start()方法是一個native方法,它將啟動一個新線程,並執行run()方法。
} }
1.2 實現Runnable接口
步驟:
1)實現Runable 接口
2)重寫父類run 方法
3)在run方法中編寫線程需求做的代碼塊
4)實例化線程類
5)先實例化Thread再把線程通過構造方法傳遞調用線程start(啟動線程)
public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } } } //為了啟動MyThread,需要首先實例化一個Thread,並傳入自己的MyThread實例:
MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start();
1.3 通過Callable接口實現多線程
Java5之后,提供了Callable接口,看起來像是Runnable接口的增強版:該接口提供call()方法來作為線程執行體。與run()相比,call()方法更強大,該方法可以有返回值,並且可以聲明拋出異常。
Callable接口介紹:
1)java.util.concurrent.Callable是一個泛型接口,只有一個call()方法
2)call()方法拋出異常Exception異常,且返回一個指定的泛型類對象
Callable接口實現多線程的應用場景:當父線程想要獲取子線程的運行結果時
實現Callable和實現Runnable類似,但是功能更強大,具體表現在
a)可以在任務結束后提供一個返回值,Runnable不行;
b)call方法可以拋出異常,Runnable的run方法不行;
c)可以通過運行Callable得到的Fulture對象監聽目標線程調用call方法的結果,得到返回值,(fulture.get(),調用后會阻塞,直到獲取到返回值).
使用Callable接口實現多線程的步驟
1)第一步:創建Callable子類的實例化對象
2)第二步:創建FutureTask對象,並將Callable對象傳入FutureTask的構造方法中(注意:FutureTask實現了Runnable接口和Future接口)
3)第三步:實例化Thread對象,並在構造方法中傳入FurureTask對象
4)第四步:啟動線程
//實現Callable重寫call方法
public class CallTask implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for (int i = 0; i < 100; i++) { sum += i; } return sum; } }
/** * 創建多線程的方式 : 4種 * 1.繼承Thread類 * 2.實現Runable接口 * 3.實現Callable接口 * 4.使用線程池創建線程 * * Callable相比Runable的區別: * 1. 線程任務有返回值 * 2. 需要使用FutureTask實現類接收返回值 * 3. futureTask.get方法獲取放回值時, 主線程會進入阻塞狀態, 等待分線程的完成 */
public class CallableTest { public static void main(String[] args) throws InterruptedException, ExecutionException { long start = System.currentTimeMillis(); CallTask callTask = new CallTask(); //使用FutureTask實現類接收返回值 泛型是返回值類型
FutureTask<Integer> futureTask = new FutureTask<>(callTask); //new Thread(futureTask).start();
for (int i = 0; i < 100; i++) { new Thread(futureTask).start(); } // 主線程會進入阻塞狀態, 等待分線程的完成 可以用於閉鎖
Integer sum = futureTask.get(); System.out.println(sum); long end = System.currentTimeMillis(); System.out.println("程序消耗時間: " + (end - start)); } }