Java 中使用 Callable 創建線程的方法

一、Callable 接口概述?

Callable接口位于java.util.concurrent包中,與Runnable接口類似,同樣用于定義線程執行的任務,但它具有以下獨特特性:?

  1. 支持返回值:Callable接口聲明了一個call()方法,該方法會在任務執行完畢后返回結果,這使得我們可以在主線程中獲取子線程的執行結果,方便進行后續處理。?
  1. 可拋出異常:call()方法允許拋出任何類型的異常,包括受檢異常,相比Runnable接口中run()方法只能通過try-catch捕獲非受檢異常,Callable在異常處理上更加靈活。?

Callable接口是一個泛型函數式接口,其定義如下:

@FunctionalInterface
public interface Callable<V> {V call() throws Exception;
}

二、使用 Callable 創建線程的方法?

1. 通過 FutureTask 結合 Thread?

FutureTask類實現了RunnableFuture接口,而RunnableFuture繼承了Runnable和Future接口,這使得FutureTask既可以作為Runnable被線程執行,又可以作為Future獲取Callable任務的執行結果。具體使用步驟如下:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;// 定義Callable實現類
class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i <= 100; i++) {sum += i;}return sum;}
}public class CallableThreadExample {public static void main(String[] args) {// 創建Callable實例Callable<Integer> callable = new MyCallable();// 創建FutureTask實例,并將Callable實例作為參數傳入FutureTask<Integer> futureTask = new FutureTask<>(callable);// 創建Thread實例,并將FutureTask作為參數傳入Thread thread = new Thread(futureTask);// 啟動線程thread.start();try {// 獲取Callable任務的執行結果Integer result = futureTask.get();System.out.println("計算結果: " + result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}
}

在上述代碼中,首先定義了一個實現Callable接口的MyCallable類,在call()方法中實現具體的計算邏輯,這里是計算 1 到 100 的整數和。然后在main方法中,創建Callable實例和對應的FutureTask實例,將FutureTask實例作為參數傳遞給Thread構造函數創建線程并啟動。最后通過futureTask.get()方法獲取Callable任務的執行結果,如果在獲取結果過程中線程被中斷或任務執行過程中拋出異常,會分別捕獲InterruptedException和ExecutionException進行處理。

2. 通過 ExecutorService 線程池

import java.util.concurrent.*;class MyCallable2 implements Callable<String> {@Overridepublic String call() throws Exception {Thread.sleep(2000);return "任務執行完成";}
}public class CallableThreadPoolExample {public static void main(String[] args) {// 創建線程池ExecutorService executorService = Executors.newFixedThreadPool(3);// 創建Callable實例Callable<String> callable = new MyCallable2();// 提交Callable任務,并返回Future對象Future<String> future = executorService.submit(callable);try {// 獲取任務執行結果String result = future.get();System.out.println(result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();} finally {// 關閉線程池executorService.shutdown();}}
}

在這段代碼中,首先通過Executors.newFixedThreadPool(3)創建了一個固定大小為 3 的線程池executorService。接著定義了一個MyCallable2類實現Callable接口,在call()方法中讓線程休眠 2 秒后返回結果。然后使用executorService.submit(callable)方法提交Callable任務,該方法會立即返回一個Future對象,通過future.get()方法獲取任務的執行結果。最后在finally塊中調用executorService.shutdown()方法關閉線程池,以釋放資源。

三、Callable 與 Runnable 的對比?

特性?

Callable?

Runnable?

返回值?

支持返回值,通過call()方法返回任務執行結果,結果類型由泛型指定?

不支持返回值,run()方法返回值為void?

異常處理?

可以拋出任何類型的異常,包括受檢異常,需要在調用端顯式處理?

只能捕獲非受檢異常,受檢異常需要在run()方法內部通過try-catch處理?

實現方式?

是一個泛型接口,需實現call()方法?

是一個普通接口,需實現run()方法?

配合使用對象?

通常與FutureTask或ExecutorService結合使用,用于獲取任務執行結果?

可直接與Thread類配合使用,或提交到線程池執行?

?

四、總結

Callable接口為 Java 多線程編程帶來了更豐富的功能和更高的靈活性,通過與FutureTask或ExecutorService線程池結合使用,我們可以方便地獲取線程執行結果并進行異常處理。在實際開發中,當我們需要在多線程任務執行完畢后獲取結果,或者需要更精細地處理任務執行過程中的異常時,Callable接口是一個非常好的選擇。同時,合理利用線程池來管理Callable任務,能夠提高程序的性能和資源利用率,讓多線程程序更加高效、穩定地運行。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79384.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79384.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79384.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025-SMS短信驗證服務或存風險,小心賬號隱私“失守”

近期&#xff0c;火絨安全情報中心監測到一款偽裝成具備SMS短信驗證碼接收服務的程序。該程序通過部署持久化后門&#xff08;即僵尸網絡節點&#xff09;竊取敏感信息。火絨安全提醒廣大用戶務必從官方或可信渠道下載軟件&#xff0c;避免因使用來路不明的程序而導致賬號被盜或…

docker部署Open WebUI下載速度慢解決方法

docker pull ghcr.nju.edu.cn/open-webui/open-webui:main改成這個就可以了

氣泡圖、桑基圖的繪制

1、氣泡圖 使用氣泡圖分析某一年中國同歐洲各國之間的貿易情況。 氣泡圖分析的三個維度&#xff1a; ? 進口額&#xff1a;橫軸 ? 出口額&#xff1a;縱軸 ? 進出口總額&#xff1a;氣泡大小 數據來源&#xff1a;鏈接: 國家統計局數據 數據概覽&#xff08;進出口總額&…

前端面經-VUE3篇(三)--vue Router(二)導航守衛、路由元信息、路由懶加載、動態路由

一、導航守衛 vue Router 中的 導航守衛&#xff08;Navigation Guards&#xff09; 是一個非常重要的功能&#xff0c;用于在路由切換過程中&#xff0c;攔截、控制、檢查或延遲頁面跳轉。 你可以理解為&#xff1a; &#x1f510; “進門前的保安”&#xff0c;控制哪些頁面…

MATLAB實現二氧化硅和硅光纖的單模光波特性與仿真

一.二氧化硅和硅光纖的單模光波特性 利用麥克斯方程的精確解研究二氧化硅和硅亞波長直徑導線的單模光波特性。研究了單模條件、模場。 二氧化硅光纖導線是圓形截面&#xff0c;包層是空氣包層&#xff0c;階梯型變化的折射率&#xff0c;導線線徑D非常小長度足夠長&#xff0…

【Linux系統】第二節—基礎指令(2)

hello ~ 好久不見 自己想要的快樂要自己好好爭取&#xff01; 云邊有個稻草人-個人主頁 Linux—本篇文章所屬專欄—歡迎訂閱—持續更新中 目錄 本節課核心指令知識點總結 本節基本指令詳解 07.man 指令 08.cp 指令 09.mv 指令 10.cat 指令 11.more 指令 12.less 指令 …

為了結合后端而學習前端的學習日志——【黑洞光標特效】

前端設計專欄 今天給大家帶來一個超酷的前端特效——黑洞光標&#xff01;讓你的鼠標變成一個會吞噬光粒子的迷你黑洞&#xff0c;點擊時還會噴射出綠色能量粒子&#xff01;&#x1f320; &#x1f680; 效果預覽 想象一下&#xff1a;你的鼠標變成一個旋轉的黑洞&#xff0…

[硬件電路-11]:模擬電路常見元器件 - 什么是阻抗、什么是輸入阻抗、什么是輸出阻抗?阻抗、輸入阻抗與輸出阻抗的全面解析

1. 阻抗&#xff08;Impedance&#xff09; 定義&#xff1a;阻抗是電路或元件對交流信號&#xff08;AC&#xff09;流動的阻礙能力&#xff0c;用符號Z表示&#xff0c;單位為歐姆&#xff08;Ω&#xff09;。它綜合了電阻&#xff08;R&#xff09;、電感&#xff08;L&am…

機器學習和深度學習的對比

深度 數據經過深層網絡后&#xff0c;語義信息表征能力強&#xff0c;對幾何細節信息表征能力弱。 數據依賴性 深度學習算法需要大量的數據來訓練&#xff0c;而傳統的機器學習使用制定的規則。所以&#xff0c;當數據量少時&#xff0c;深度學習的性能差于機器學習&#xf…

Kubernetes 安裝 minikube

安裝 minikube 在 Ubuntu 上安裝 minikube minikube 是一個工具&#xff0c;它可以在本地快速運行一個單節點的 Kubernetes 集群。它主要用于&#xff1a;本地學習 Kubernetes、測試和開發 Kubernetes 應用程序、快速嘗試 Kubernetes 的功能。 系統配置最低要求如下 CPU&#…

【學習筆記】深度學習:典型應用

作者選擇了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰寫的《Deep Learning》(人工智能領域的經典教程&#xff0c;深度學習領域研究生必讀教材),開始深度學習領域學習&#xff0c;深入全面的理解深度學習的理論知識。 之前的文章參考下面的鏈接&#xf…

ComputeShader繪制全屏純色紋理

參考 Getting Started With Compute Shaders In Unity 環境 Win10 Unity20194.40 全屏純色紋理示例 使用ComputerShader逐個像素設置顏色 ComputeShader腳本 設置紋理顏色 #pragma kernel CSMainRWTexture2D<float4> Result;//紋理 half4 solidColor;//顏色[numth…

數學實驗(Matlab語言環境和線性代數實驗)

一、Matlab語言環境和線性代數實驗 1.Matlab語言環境 Matlab簡介 Matlab&#xff1a;Matrix Laboratry 矩陣實驗室 Matlab 提供了強大的科學計算、靈活的程序設計流程、高質量的圖形可視化與界面設計等功能&#xff0c;被廣泛應用于科學計算、控制系統、信息處理等領域的分…

Android面試總結之GC算法篇

一、GC 機制核心原理與算法 面試題 1&#xff1a;Android 中為什么采用分代回收&#xff1f;分代策略如何優化 GC 效率&#xff1f; 標準答案&#xff1a; 分代回收基于對象生命周期的差異&#xff0c;將堆分為年輕代&#xff08;Young Gen&#xff09;和老年代&#xff08;Ol…

仿騰訊會議——注冊登錄UI

1、加載素材 2、新添加資源類 3、加載圖片 4、添加左側圖片 在左側添加一個標簽 選擇圖片 選擇圖片 勾選保證圖片不變形 5、修改組件名稱 6、設置密碼輸入框 5、切換 6、編輯提示框 7、定義提交和清空的槽函數 8、設置頁面標題和最先顯示頁面 9、清空登錄信息函數實現 10、清空…

Kotlin 常見問題

以下從基礎、中級、高級三個難度等級為你提供 Kotlin 面試題及參考答案&#xff1a; 基礎難度 1. Kotlin 中 val 和 var 的區別是什么&#xff1f; 答案要點&#xff1a;val 用于聲明不可變變量&#xff0c;類似于 Java 中的 final 變量&#xff0c;一旦賦值后就不能再重新賦…

高頻數據沖擊數據庫的技術解析與應對方案

目錄 前言一、問題現象與影響分析1.1 典型場景表現1.2 核心問題分類 二、失效根源深度剖析2.1 架構設計缺陷2.2 緩存策略缺陷 三、解決方案與最佳實踐3.1 緩存架構設計3.1.1 分層緩存架構3.1.2 熱點數據識別 3.2 緩存策略優化3.2.1 動態過期時間算法3.2.2 緩存更新策略對比 3.3…

[Spring] Sentinel詳解

&#x1f338;個人主頁:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;?熱門專欄: &#x1f9ca; Java基本語法(97平均質量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection與…

清除浮動的重要性及解決辦法

由于父級盒子很多情況下&#xff0c;不方便給高度&#xff0c;但是子盒子浮動又不占有位置&#xff0c;最后父級盒子高度為0時&#xff0c;就會影響下面的標準流盒子。 一、為什么要清除浮動 父元素高度塌陷&#xff1a; 如果父元素內部的所有子元素都浮動了&#xff0c;并且沒…

域名與官網的迷思:數字身份認證的全球困境與實踐解方-優雅草卓伊凡

域名與官網的迷思&#xff1a;數字身份認證的全球困境與實踐解方-優雅草卓伊凡 一、官網概念的法律與技術界定 1.1 官網的實質定義 當卓伊凡被問及”公司域名就是官網嗎”這一問題時&#xff0c;他首先指出&#xff1a;”這相當于問’印著某公司logo的建筑就是該公司總部嗎’…