成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

騰訊一面:Thread、Runnable、Callable、Future、FutureTask,談談他們的關系?

開發 前端
對于 FutureTask,Callable 就是他的任務,而 FutureTask 內部維護了一個任務狀態,所有的狀態都是圍繞這個任務來進行的,隨著任務的進行,狀態也在不斷的更新。

大家好,我是樓仔!

Thread、Runnable、Callable、Future、FutureTask,你能詳細講出他們的內部關系么?這也是面試經常問到的問題。

這篇文章主要告訴大家各種對象內部的關系,能達到靈活運用的境界,下面是文章目錄:

圖片

1. Thread 和 Runnable

1.1 Thread

我們先看一下 Thread 最簡單的使用姿勢:

public class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + "已經運行");

}
public static void main(String[] args) {
new MyThread("線程一").start();
}
}

線程包含 4 個狀態:創建 -> 就緒 -> 運行 -> 結束。

當執行 start() 后,線程進入就緒狀態,當對應的線程搶占到 cpu 調度資源之后,進入運行狀態,此時調用的是 run 方法,執行完畢之后就結束了。

1.2 Runnable

我們看一下 Runnable 最簡單的使用姿勢:

public class MyTask implements Runnable {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + "已經運行");
}
public static void main(String[] args) {
new Thread(new MyTask(),"線程二").start();
}
}

這里 MyTask 就是一個 Runnable,實現了 run() 方法,作為 Thread() 的入參。

基本所有同學都知道這樣使用,但是你們知道原理么?

1.3 Thread 和 Runnable 的關系

我們看一下 Runnable 的接口定義:

public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}

英文翻譯大致如下:當一個對象繼承并實現了 run() 方法,當線程 start() 后,會在該線程中單獨執行該對象的 run() 方法。

這段翻譯,基本就告訴了 Runnable 和 Thread 的關系:

  • MyTask 繼承 Runnable,并實現了 run() 方法;
  • Thread 初始化,將 MyTask 作為自己的成員變量;
  • Thread 執行 run() 方法,線程處于“就緒”狀態;
  • 等待 CPU 調度,執行 Thread 的 run() 方法,但是 run() 的內部實現,其實是執行的 MyTask.run() 方法,線程處于“運行”狀態。

這里面的第2、4步,需要對照著源碼看看。

在 Thread 初始化時,MyTask 作為入參 target,最后賦值給 Thread.target:

圖片

圖片

當執行 Thread.run() 時,其實是執行的 target.run(),即 MyTask.run(),這個是典型的策略模式:

圖片

2. Callable 、Future 和 FutureTask

先看一下它們的整體關系圖譜:

圖片

我剛開始看到這幅圖,感覺 Java 真是麻煩,已經有了 Thread 和 Runnable 這兩種創建線程的方式,為啥又搞這 3 個東西呢?

其實對于 Thread 和 Runable,其 run() 都是無返回值的,并且無法拋出異常,所以當你需要返回多線程的數據,就需要借助 Callable 和 Feature。

2.1 Callable

Callable 是一個接口,里面有個 V call() 方法,這個 V 就是我們的返回值類型:

public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}

我們一般會用匿名類的方式使用 Callable,call() 中是具體的業務邏輯:

Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
// 執行業務邏輯 ...
return "this is Callable is running";
}
};

這里拋出一個問題,這個 callable.call() 和 Thread.run() 是什么關系呢?

2.2 FutureTask

通過關系圖譜,FutureTask 繼承了 RunnableFuture,RunnableFuture 繼承了 Runnable 和 Future:

public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}

所以,FutureTask 也是個 Runnable !!!

這里就有點意思了,既然 FutureTask 是個 Runnable,肯定就需要實現 FutureTask.run() 方法,那么 FutureTask 也可以作為 Thread 的初始化入參,使用姿勢如下:

new Thread(FutureTask對象).start();

所以當執行 Thread.run() 時,其實是執行的 FutureTask.run(),這個是我們破解的第一層。

下面我們再破解 FutureTask.run() 和 Callable.call() 的關系。

2.3 Callable 和 FutureTask 的關系

FutureTask 初始化時,Callable 必須作為 FutureTask 的初始化入參:

圖片

當執行 FutureTask.run() 時,其實執行的是 Callable.call():

圖片

所以,這里又是一個典型的策略模式 !!!

現在我們應該可以很清楚知道 Thread 、Runnable、FutureTask 和 Callable 的關系:

Thread.run() 執行的是 Runnable.run();

FutureTask 繼承了 Runnable,并實現了 FutureTask.run();

FutureTask.run() 執行的是 Callable.run();

依次傳遞,最后 Thread.run(),其實是執行的 Callable.run()。

所以整個設計方法,其實就是 2 個策略模式,Thread 和 Runnable 是一個策略模式,FutureTask 和 Callable 又是一個策略模式,最后通過 Runnable 和 FutureTask 的繼承關系,將這 2 個策略模式組合在一起。

嗯嗯。。。我們是不是把 Future 給忘了~~

2.4 Future

為什么要有 Future 呢?我再問一個問題,大家可能就知道了。

我們通過 FutureTask,借助 Thread 執行線程后,結果數據我們怎么獲取到呢?這里就需要借助到 Future。

我們看一下 Future 接口:

public interface Future<V> {
// 取消任務,如果任務正在運行的,mayInterruptIfRunning為true時,表明這個任務會被打斷的,并返回true;
// 為false時,會等待這個任務執行完,返回true;若任務還沒執行,取消任務后返回true,如任務執行完,返回false
boolean cancel(boolean mayInterruptIfRunning);
// 判斷任務是否被取消了,正常執行完不算被取消
boolean isCancelled();
// 判斷任務是否已經執行完成,任務取消或發生異常也算是完成,返回true
boolean isDone();
// 獲取任務返回結果,如果任務沒有執行完成則等待完成將結果返回,如果獲取的過程中發生異常就拋出異常,
// 比如中斷就會拋出InterruptedException異常等異常
V get() throws InterruptedException, ExecutionException;
// 在規定的時間如果沒有返回結果就會拋出TimeoutException異常
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

對于 FutureTask,Callable 就是他的任務,而 FutureTask 內部維護了一個任務狀態,所有的狀態都是圍繞這個任務來進行的,隨著任務的進行,狀態也在不斷的更新。

FutureTask 繼承了 Future,實現對任務的取消、數據獲取、任務狀態判斷等功能。

比如我們經常會調用 get() 方法獲取數據,如果任務沒有執行完成,會將當前線程放入阻塞隊列等待,當任務執行完后,會喚醒阻塞隊列中的線程。

3. 具體實例

private static List<String> processByMultiThread(Integer batchSize) throws ExecutionException, InterruptedException {
List<String> output = new ArrayList<>();

// 獲取分批數據
List<List<Integer>> batchProcessData = getProcessData(batchSize);

// 啟動線程
List<FutureTask<List<String>>> futureTaskList = new ArrayList<>();
for (List<Integer> processData : batchProcessData) {
Callable<List<String>> callable = () -> processOneThread(processData);
FutureTask<List<String>> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start(); // 啟動線程
futureTaskList.add(futureTask);
}

// 獲取線程返回的數據
for (FutureTask futureTask : futureTaskList) {
List<String> processData = (List<String>) futureTask.get();
output.addAll(processData);
}
return output;
}

這個示例很簡單:

  • 先將數據按照 batchSize 分成 N 批;
  • 啟動 N 個線程,去執行任務;
  • 通過 futureTask.get() 獲取每個線程數據,并匯總輸出。

這個示例其實不太適合線上的場景,因為每次調用都會初始化線程,如果調用過多,內存可能會被撐爆,需要借助線程池。

責任編輯:武曉燕 來源: 樓仔
相關推薦

2022-06-02 11:12:10

CallableFuture

2025-03-07 00:11:00

JWTJSONSession

2024-06-06 09:03:37

MySQL數據庫共享鎖

2022-05-11 22:15:51

云計算云平臺

2009-07-30 14:38:36

云計算

2020-09-19 17:46:20

React Hooks開發函數

2011-12-22 20:53:40

Android

2011-12-23 09:43:15

開源開放

2022-05-24 08:09:00

HadoopHiveSpark

2024-05-15 16:41:57

進程IO文件

2022-01-17 07:59:13

SpringSpringMVCSpringBoot

2022-05-24 12:57:49

函數代碼Java

2012-12-19 09:04:29

2025-04-01 08:40:00

HTTPRPC開發

2020-12-07 09:40:19

Future&Futu編程Java

2024-11-11 16:40:04

2012-03-01 14:04:03

Java

2025-05-29 10:30:00

C++編程recv

2013-09-16 10:52:09

2020-07-13 23:22:02

物聯網電子技術
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 操视频网站 | 蜜臀网| 亚洲一区二区高清 | 日韩av免费在线观看 | 日韩精品一区二区三区在线播放 | www.国产精品| 国产精品久久久久久久久久免费 | 亚洲国产精品网站 | 国产一区二区 | 亚洲国产精品一区在线观看 | 免费观看的av毛片的网站 | 日韩中文字幕在线观看 | 91精品久久久久久综合五月天 | 成人av网页| 亚洲精品一区在线 | 亚洲一区二区三区四区五区中文 | 国产在线视频一区二区 | 91视频官网| 欧美在线观看一区 | 在线毛片网 | 日韩国产精品一区二区三区 | 97超碰在线播放 | 色噜噜狠狠色综合中国 | av毛片在线免费观看 | 一级黄色片在线看 | 日韩一区二区三区精品 | 特黄一级 | 精品亚洲一区二区三区四区五区高 | 一区中文 | 99久久精品免费视频 | 亚洲免费观看视频网站 | 三极网站| 国产a视频 | 精品欧美乱码久久久久久1区2区 | 久久视频精品 | av在线免费网 | 国产91亚洲精品一区二区三区 | 黄a在线播放 | 日韩欧美视频免费在线观看 | 久久69精品久久久久久久电影好 | 精品国产一区二区国模嫣然 |