FutureTask FutureTask是Future的實現,用來非同步任務的獲取結果,可以啟動和取消非同步任務,查詢非同步任務是否計算結束以及獲取最終的非同步任務的結果。通過get()方法來獲取非同步任務的結果,但是會阻塞當前線程直至非同步任務執行結束。一旦任務執行結束,任務不能重新啟動或取消,除非調用ru ...
FutureTask
FutureTask是Future的實現,用來非同步任務的獲取結果,可以啟動和取消非同步任務,查詢非同步任務是否計算結束以及獲取最終的非同步任務的結果。通過get()方法來獲取非同步任務的結果,但是會阻塞當前線程直至非同步任務執行結束。一旦任務執行結束,任務不能重新啟動或取消,除非調用runAndReset()方法。
代碼示例:
public class ThreadTest {
public static void main(String[] args) throws Exception {
Callable<String> myCallable = new MyCallableThread();
FutureTask<String> futureTask = new FutureTask<>(myCallable);
Thread myCallableThread = new Thread(futureTask);
myCallableThread.setName("MyThread-implements-Callable-test");
myCallableThread.start();
System.out.println("Run by Thread:" + futureTask.get());
//通過線程池執行
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(futureTask);
executorService.shutdown();
System.out.println("Run by ExecutorService:" + futureTask.get());
}
}
class MyCallableThread implements Callable<String> {
@Override
public String call() throws Exception {
return Thread.currentThread().getName();
}
}
實現一個自己的FutureTask
根據FutureTask核心原理,要實現一個FutureTask必須滿足以下方面:
- 需要泛型定義用以返回結果類型
- 需要一個callable對象,在構造方法中傳入
- 需要實現runnable介面,在run方法中實現具體結果計算
- 需要一個公開的get方法來獲取結果
- 如果線程沒有執行完,則調用get方法的線程需要進入等待隊列
- 需要一個欄位記錄線程執行的狀態
- 需要一個等待隊列存儲等待結果的線程
代碼示例:
/**
* 1. 泛型定義
* 2. 構造方法 callable
* 3. 實現了runnable
* 4. get方法返回callable執行結果
* 5. get方法有阻塞的效果(未執行結束的話)
*/
public class MyFutureTask<T> implements Runnable {
// 程式執行的結果
private T result;
// 要執行的任務
private Callable<T> callable;
// 任務運行的狀態
private volatile int state = NEW;
// 任務運行的狀態值
private static final int NEW = 0;
private static final int RUNNING = 1;
private static final int FINISHED = 2;
// 獲取結果的線程等待隊列
LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>(100);
// 執行當前FutureTask的線程,用CAS進行爭搶
AtomicReference<Thread> runner = new AtomicReference<>();
public MyFutureTask(Callable<T> task) {
this.callable = task;
}
@Override
public void run() {
// 判斷當前對象的狀態,如果是New且搶鎖成功就執行
if (state != NEW || !runner.compareAndSet(null, Thread.currentThread())) return;
state = RUNNING;
try {
result = callable.call();
} catch (Exception e) {
e.printStackTrace();
} finally {
state = FINISHED;
}
// 方法執行完,喚醒所有線程
while (true) {
Thread waiterThread = waiters.poll();
if (waiterThread == null) break;
LockSupport.unpark(waiterThread);
}
}
public T get() {
// 如果狀態不是FINISHED,則進入等待隊列
if (state != FINISHED) {
waiters.offer(Thread.currentThread());
}
while (state != FINISHED) {
LockSupport.park();
}
return result;
}
}
// MyFutureTask 測試
public class FutureTaskTest {
public static void main(String[] args) {
Callable<String> myCallable = new MyCallableThread();
MyFutureTask<String> futureTask = new MyFutureTask<>(myCallable);
Thread myCallableThread = new Thread(futureTask);
myCallableThread.setName("MyFutureTask-test");
myCallableThread.start();
System.out.println("Run by Thread:" + futureTask.get());
}
}
class MyCallableThread implements Callable<String> {
@Override
public String call() throws Exception {
return Thread.currentThread().getName();
}
}
更多相關文章
-
面試前很有必要針對性的多刷題,大部分童鞋實戰能力強,理論不行,面試前不做準備很吃虧。這裡整理了很多常考面試題,希望對你有幫助。 面試技術文 Java崗 面試考點精講(基礎篇01期) Java崗 面試考點精講(基礎篇02期) Java崗 面試考點精講(網路篇03期) Java 面試中遇到的坑 Java ...
-
原文 https://medium.com/netflix techblog/re architecting the video gatekeeper f7b0ac2f6b00 本文介紹了了內容配置工程團隊使用Hollow,一個Netflix OSS技術,重新架構與簡化我們內容管道上的基礎組件 在流 ...
-
1、什麼是CSRF攻擊? CSRF是跨站請求偽造(Cross-site request forgery)的英文縮寫\ Laravel框架中避免CSRF攻擊很簡單:Laravel自動為每個用戶Session生成了一個CSRF Token,該Token可用於驗證登錄用戶和發起請求者是否是同一人,如果不是 ...
-
本文屬於SpringMVC的入門篇,屬於基礎知識,僅供學習分享使用,如有不足之處,還請指正。 ...
-
[TOC] java實現發簡訊功能 前言 如今發簡訊功能已經成為互聯網公司的標配,本篇文章將一步步實現java發送簡訊 考察了許多提供簡訊服務的三方,幾乎所有都需要企業認證才可以使用,這對於個人學習非常不方便。多方比較之後,選擇了騰訊雲(此處並非做廣告),原因有兩點: 1. 支持微信公眾號認證(門檻 ...
-
單元測試根據級別不同可分為:單元測試、集成測試、系統測試、驗收測試、回歸測試 單元測試的更能特點:對代碼最基本單元(函數、方法)的測試、 給予特定條件判斷結果是否符合預期 相對整個程式的測試,單元測試簡化了測試任務 unittest 模塊 代碼組織: 斷言:assertEqual(值,表達式) 是否 ...
-
<! more https://t.zsxq.com/UnA2jIi 博客 1、 "Flink 從0到1學習 —— Apache Flink 介紹" 2、 "Flink 從0到1學習 —— Mac 上搭建 Flink 1.6.0 環境並構建運行簡單程式入門" 3、 "Flink 從0到1學習 —— ...
-
類的構成 類(Class) 由3個部分構成 類的名稱:類名 類的屬性:一組數據 類的方法:允許對進行操作的方法 (行為) 定義類 創建對象 Student類擁有的屬性數據 __init__()方法 __init___方法傳遞參數 __init___方法總結 定義__str__()方法 當使用prin ...