Java創(chuàng)建線程的四種方式
1.繼承Thread類創(chuàng)建線程
- 定義Thread類的子類矢赁,并重寫該類的run方法哮幢,run()方法的內(nèi)容就是該線程執(zhí)行的內(nèi)容
- 創(chuàng)建Thread子類的實(shí)例,即創(chuàng)建了線程對(duì)象扇救。
- 調(diào)用線程對(duì)象的start()方法來(lái)啟動(dòng)該線程刑枝。
代碼演示
public class MyThread extends Thread {
@Override
public void run() {
// 執(zhí)行業(yè)務(wù)邏輯
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
2.通過(guò)Runnable接口創(chuàng)建線程類
- 定義runnable接口的實(shí)現(xiàn)類,并重寫該接口的run()方法迅腔,該run()方法的方法體同樣是該線程的線程執(zhí)行體装畅。
- 創(chuàng)建 Runnable實(shí)現(xiàn)類的實(shí)例,并依此實(shí)例作為Thread的target來(lái)創(chuàng)建Thread對(duì)象沧烈,該Thread對(duì)象才是真正的線程對(duì)象掠兄。
- 調(diào)用線程對(duì)象的start()方法來(lái)啟動(dòng)該線程。
代碼演示
public class MyRunnable implements Runnable {
@Override
public void run() {
// 執(zhí)行業(yè)務(wù)邏輯
}
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}
3.使用Callable接口和FutureTask類實(shí)現(xiàn)創(chuàng)建有返回結(jié)果的線程
FutureTask 的出現(xiàn)是為了彌補(bǔ) Thread 的不足而設(shè)計(jì)的,可以讓程序員跟蹤、獲取任務(wù)的執(zhí)行情況蚂夕、計(jì)算結(jié)果
- 創(chuàng)建Callable接口的實(shí)現(xiàn)類迅诬,并實(shí)現(xiàn)call()方法,該call()方法將作為線程執(zhí)行體婿牍,并且有返回值百框。
- 創(chuàng)建Callable實(shí)現(xiàn)類的實(shí)例,使用FutureTask類來(lái)包裝Callable對(duì)象牍汹,該FutureTask對(duì)象封裝了該Callable對(duì)- 象的call()方法的返回值。
- 使用FutureTask對(duì)象作為Thread對(duì)象的target創(chuàng)建并啟動(dòng)新線程柬泽。
- 調(diào)用FutureTask對(duì)象的get()方法來(lái)獲得子線程執(zhí)行結(jié)束后的返回值慎菲。
代碼演示
public class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("子線程開(kāi)始計(jì)算");
Thread.sleep(2000);
System.out.println("子線程結(jié)束計(jì)算");
return 100 * 100;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 實(shí)例化Callable對(duì)象
MyCallable myCallable = new MyCallable();
// 使用FutureTask包裝
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
// 創(chuàng)建一個(gè)線程執(zhí)行任務(wù)
Thread thread = new Thread(futureTask);
thread.start();
Thread.sleep(1000);
System.out.println("主線程執(zhí)行");
// 使用get()方法會(huì)阻塞主線程,直到子線程執(zhí)行完成返回結(jié)果
int result = futureTask.get();
System.out.println("子線程計(jì)算結(jié)果: " + result);
}
}
執(zhí)行結(jié)果
子線程開(kāi)始計(jì)算
主線程執(zhí)行
子線程結(jié)束計(jì)算
子線程計(jì)算結(jié)果: 10000
4.使用線程池創(chuàng)建線程
為什么要使用線程池呢锨并?
當(dāng)不是執(zhí)行一次性任務(wù)的時(shí)候露该,如果不使用線程池,那么就要頻繁的創(chuàng)建和銷毀線程第煮,這是一個(gè)比較消耗資源的操作解幼,使用線程池可以靈活的調(diào)整線程資源的占用,防止消耗過(guò)多的內(nèi)存
在Java中已經(jīng)提供了ExecutorSerice包警、Executors等工具類為我們快速的創(chuàng)建線程池
常用的常見(jiàn)線程的方法有
- Executors.newFixedThreadPool(int nThreads) --- 創(chuàng)建固定線程數(shù)量的線程池
- Executors.newSingleThreadPool() --- 創(chuàng)建只包含一個(gè)線程的線程池
- Executors.newCachedThreadPool() --- 創(chuàng)建一個(gè)可緩存的線程池撵摆。如果線程池的當(dāng)前規(guī)模超過(guò)了處理需求時(shí),那么就會(huì)回收部分空閑的線程(根據(jù)空閑時(shí)間來(lái)回收)害晦,當(dāng)需求增加時(shí)特铝,此線程池又可以智能的添加新線程來(lái)處理任務(wù)。此線程池不會(huì)對(duì)線程池大小做限制壹瘟,線程池大小完全依賴于操作系統(tǒng)(或者說(shuō)JVM)能夠創(chuàng)建的最大線程大小鲫剿。
- Executors.newScheduledThreadPool() --- 創(chuàng)建了一個(gè)固定長(zhǎng)度的線程池,而且以延遲或定時(shí)或周期的方式來(lái)執(zhí)行任務(wù)稻轨,類似于Timer灵莲。可應(yīng)用于重發(fā)機(jī)制殴俱。