Java中使用Callable創(chuàng)建線程的方法
一、Callable 接口概述?
Callable接口位于java.util.concurrent包中,與Runnable接口類(lèi)似,同樣用于定義線程執(zhí)行的任務(wù),但它具有以下獨(dú)特特性:?
- 支持返回值:Callable接口聲明了一個(gè)call()方法,該方法會(huì)在任務(wù)執(zhí)行完畢后返回結(jié)果,這使得我們可以在主線程中獲取子線程的執(zhí)行結(jié)果,方便進(jìn)行后續(xù)處理。?
- 可拋出異常:call()方法允許拋出任何類(lèi)型的異常,包括受檢異常,相比Runnable接口中run()方法只能通過(guò)try-catch捕獲非受檢異常,Callable在異常處理上更加靈活。?
Callable接口是一個(gè)泛型函數(shù)式接口,其定義如下:
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}二、使用 Callable 創(chuàng)建線程的方法?
1. 通過(guò) FutureTask 結(jié)合 Thread?
FutureTask類(lèi)實(shí)現(xiàn)了RunnableFuture接口,而RunnableFuture繼承了Runnable和Future接口,這使得FutureTask既可以作為Runnable被線程執(zhí)行,又可以作為Future獲取Callable任務(wù)的執(zhí)行結(jié)果。具體使用步驟如下:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
// 定義Callable實(shí)現(xiàn)類(lèi)
class MyCallable implements Callable<Integer> {
@Override
public 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) {
// 創(chuàng)建Callable實(shí)例
Callable<Integer> callable = new MyCallable();
// 創(chuàng)建FutureTask實(shí)例,并將Callable實(shí)例作為參數(shù)傳入
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 創(chuàng)建Thread實(shí)例,并將FutureTask作為參數(shù)傳入
Thread thread = new Thread(futureTask);
// 啟動(dòng)線程
thread.start();
try {
// 獲取Callable任務(wù)的執(zhí)行結(jié)果
Integer result = futureTask.get();
System.out.println("計(jì)算結(jié)果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}在上述代碼中,首先定義了一個(gè)實(shí)現(xiàn)Callable接口的MyCallable類(lèi),在call()方法中實(shí)現(xiàn)具體的計(jì)算邏輯,這里是計(jì)算 1 到 100 的整數(shù)和。然后在main方法中,創(chuàng)建Callable實(shí)例和對(duì)應(yīng)的FutureTask實(shí)例,將FutureTask實(shí)例作為參數(shù)傳遞給Thread構(gòu)造函數(shù)創(chuàng)建線程并啟動(dòng)。最后通過(guò)futureTask.get()方法獲取Callable任務(wù)的執(zhí)行結(jié)果,如果在獲取結(jié)果過(guò)程中線程被中斷或任務(wù)執(zhí)行過(guò)程中拋出異常,會(huì)分別捕獲InterruptedException和ExecutionException進(jìn)行處理。
2. 通過(guò) ExecutorService 線程池
import java.util.concurrent.*;
class MyCallable2 implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "任務(wù)執(zhí)行完成";
}
}
public class CallableThreadPoolExample {
public static void main(String[] args) {
// 創(chuàng)建線程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 創(chuàng)建Callable實(shí)例
Callable<String> callable = new MyCallable2();
// 提交Callable任務(wù),并返回Future對(duì)象
Future<String> future = executorService.submit(callable);
try {
// 獲取任務(wù)執(zhí)行結(jié)果
String result = future.get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
// 關(guān)閉線程池
executorService.shutdown();
}
}
}在這段代碼中,首先通過(guò)Executors.newFixedThreadPool(3)創(chuàng)建了一個(gè)固定大小為 3 的線程池executorService。接著定義了一個(gè)MyCallable2類(lèi)實(shí)現(xiàn)Callable接口,在call()方法中讓線程休眠 2 秒后返回結(jié)果。然后使用executorService.submit(callable)方法提交Callable任務(wù),該方法會(huì)立即返回一個(gè)Future對(duì)象,通過(guò)future.get()方法獲取任務(wù)的執(zhí)行結(jié)果。最后在finally塊中調(diào)用executorService.shutdown()方法關(guān)閉線程池,以釋放資源。
三、Callable 與 Runnable 的對(duì)比?
特性? | Callable? | Runnable? |
返回值? | 支持返回值,通過(guò)call()方法返回任務(wù)執(zhí)行結(jié)果,結(jié)果類(lèi)型由泛型指定? | 不支持返回值,run()方法返回值為void? |
異常處理? | 可以拋出任何類(lèi)型的異常,包括受檢異常,需要在調(diào)用端顯式處理? | 只能捕獲非受檢異常,受檢異常需要在run()方法內(nèi)部通過(guò)try-catch處理? |
實(shí)現(xiàn)方式? | 是一個(gè)泛型接口,需實(shí)現(xiàn)call()方法? | 是一個(gè)普通接口,需實(shí)現(xiàn)run()方法? |
配合使用對(duì)象? | 通常與FutureTask或ExecutorService結(jié)合使用,用于獲取任務(wù)執(zhí)行結(jié)果? | 可直接與Thread類(lèi)配合使用,或提交到線程池執(zhí)行? |
四、總結(jié)
Callable接口為 Java 多線程編程帶來(lái)了更豐富的功能和更高的靈活性,通過(guò)與FutureTask或ExecutorService線程池結(jié)合使用,我們可以方便地獲取線程執(zhí)行結(jié)果并進(jìn)行異常處理。在實(shí)際開(kāi)發(fā)中,當(dāng)我們需要在多線程任務(wù)執(zhí)行完畢后獲取結(jié)果,或者需要更精細(xì)地處理任務(wù)執(zhí)行過(guò)程中的異常時(shí),Callable接口是一個(gè)非常好的選擇。同時(shí),合理利用線程池來(lái)管理Callable任務(wù),能夠提高程序的性能和資源利用率,讓多線程程序更加高效、穩(wěn)定地運(yùn)行。
到此這篇關(guān)于Java中使用Callable創(chuàng)建線程的方法的文章就介紹到這了,更多相關(guān)Java Callable創(chuàng)建線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java Unicode和UTF-8之間轉(zhuǎn)換實(shí)例
這篇文章主要介紹了java Unicode和UTF-8之間轉(zhuǎn)換實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
Springboot中@ConfigurationProperties輕松管理應(yīng)用程序的配置信息詳解
通過(guò)@ConfigurationProperties注解,可以將外部配置文件中的屬性值注入到JavaBean中,簡(jiǎn)化了配置屬性的讀取和管理,這使得SpringBoot應(yīng)用程序中配置文件的屬性值可以映射到POJO類(lèi)中,實(shí)現(xiàn)類(lèi)型安全的屬性訪問(wèn),此方法避免了手動(dòng)讀取配置文件屬性的需要2024-10-10
Java并發(fā)的CAS原理與ABA問(wèn)題的講解
今天小編就為大家分享一篇關(guān)于Java并發(fā)的CAS原理與ABA問(wèn)題的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01
基于Java實(shí)現(xiàn)Socket編程入門(mén)
Java最初是作為網(wǎng)絡(luò)編程語(yǔ)言出現(xiàn)的,使得客戶(hù)端和服務(wù)器的溝通變成了現(xiàn)實(shí),而在網(wǎng)絡(luò)編程中,使用最多的就是Socket,本文就來(lái)介紹一下基于Java實(shí)現(xiàn)Socket編程入門(mén),感興趣的可以來(lái)了解一下2022-03-03
java虛擬機(jī)原理:Class字節(jié)碼二進(jìn)制文件分析
class文件全名稱(chēng)為Java class文件,主要在平臺(tái)無(wú)關(guān)性和網(wǎng)絡(luò)移動(dòng)性方面使Java更適合網(wǎng)絡(luò)。它在平臺(tái)無(wú)關(guān)性方面的任務(wù)是:為Java程序提供獨(dú)立于底層主機(jī)平臺(tái)的二進(jìn)制形式的服務(wù)。下面我們來(lái)詳細(xì)解讀下它吧2021-09-09
淺談Java(SpringBoot)基于zookeeper的分布式鎖實(shí)現(xiàn)
這篇文章主要介紹了Java(SpringBoot)基于zookeeper的分布式鎖實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
生成8位隨機(jī)不重復(fù)的數(shù)字編號(hào)的方法
生成隨機(jī)不重復(fù)的數(shù)字編號(hào)在某些情況下也會(huì)用到,本文以生成8位隨機(jī)不重復(fù)的數(shù)字編號(hào)為例與大家分享下具體的實(shí)現(xiàn)過(guò)程,感興趣的朋友可以參考下2013-09-09
短網(wǎng)址的原理與生成方法(Java實(shí)現(xiàn))
這篇文章主要給大家介紹了關(guān)于短網(wǎng)址的原理與生成方法,利用的是Java實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10

