Java使用Runnable和Callable實現(xiàn)多線程的區(qū)別詳解
使用Runnable和Callable接口實現(xiàn)多線程的區(qū)別
先看兩種實現(xiàn)方式的步驟:
1.實現(xiàn)Runnable接口
public class ThreadDemo{
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
//創(chuàng)建并啟動由實現(xiàn)Runnable接口創(chuàng)建的線程
new Thread(new Runner(),"Thread"+i).start();
}
}
}
//實現(xiàn)Runnable接口
class Runner implements Runnable{
//實現(xiàn)run方法
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"有實現(xiàn)Runnable接口創(chuàng)建");
}
}
2.實現(xiàn) Callable 接口
public class ThreadDemo{
public static void main(String[] args) throws ExecutionException, InterruptedException {
for (int i = 1; i <= 5; i++) {
//使用FutureTask保存線程結(jié)果
FutureTask<String> futureTask = new FutureTask<String>(new Caller());
//創(chuàng)建并啟動由實現(xiàn)Callable創(chuàng)建的線程
new Thread(futureTask,"Thread"+i).start();
//獲取線程執(zhí)行結(jié)果
System.out.println(futureTask.get());
}
}
}
//實現(xiàn)Callable接口
class Caller implements Callable{
//實現(xiàn)Call接口
@Override
public Object call() throws Exception {
String result = Thread.currentThread().getName()+"由實現(xiàn)Callable接口創(chuàng)建";
return result;
}
}
從以上代碼可以看出,使用 Callable 接口創(chuàng)建多線程時使用了 FutureTask 進(jìn)行封裝,然后 FutureTask 作為參數(shù)傳給 Thread 的構(gòu)造函數(shù),而 FutureTask 的作用是存放 Callable 接口 call 方法的返回值。我們來看一下 FutureTask 的源碼
//FutureTask實現(xiàn)了RunnableFuture接口
public class FutureTask<V> implements RunnableFuture<V> {}
//再看RunnableFuture接口,繼承了Runnable接口
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
//回到FutureTask,找到run方法
public void run() {
...
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
//獲取call的返回值
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
...
}
//看一下set方法
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
...
}
}
//再看一下FutureTask的構(gòu)造函數(shù)
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
從對 FutureTask 的源碼分析,我們可以看出 FutureTask 實現(xiàn)了 Runnable 接口的 run 方法,在 run 方法中調(diào)用了 Callable 的 call 方法,將結(jié)果保存到 result 中,通過 set 方法將結(jié)果存儲至 outcome 變量中。
通過以上分析,我們總結(jié)出使用 Runnable 和 Callable 接口的區(qū)別:
1.使用 Runnable 接口實現(xiàn)更加簡單,而 通過 Callable 接口創(chuàng)建線程需要 FutureTask 進(jìn)行封裝;
2.通過實現(xiàn) Runnable 接口創(chuàng)建的線程沒有返回值,而使用 Callable 接口創(chuàng)建的線程可以有返回結(jié)果,并保存在 FutureTask中;
3.通過實現(xiàn) Runnable 接口創(chuàng)建線程不拋出異常,而使用 Callable 接口創(chuàng)建的線程會拋出異常;
從以上總結(jié)可以看出,我們也可以看出 Runnable 適用于無需返回值的場景,而 Callable 接口用于需要保存返回值的場景。
到此這篇關(guān)于Java使用Runnable和Callable實現(xiàn)多線程的區(qū)別詳解的文章就介紹到這了,更多相關(guān)Java Runnable Callable多線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java使用多線程批次查詢大量數(shù)據(jù)(Callable返回數(shù)據(jù))方式
- Java通過Callable實現(xiàn)多線程
- Java多線程中Callable和Future的解讀
- Java中的Callable實現(xiàn)多線程詳解
- Java使用Callable接口實現(xiàn)多線程的實例代碼
- Java多線程實現(xiàn)之Callable詳解
- Java中Runnable和Callable分別什么時候使用
- Java中Runnable與Callable接口的區(qū)別詳解
- 詳解Java中Callable和Future的區(qū)別
- java面試常問的Runnable和Callable的區(qū)別
- Java并發(fā)教程之Callable和Future接口詳解
- Java中callable的實現(xiàn)原理
相關(guān)文章
如何在Spring?Boot中使用MyBatis訪問數(shù)據(jù)庫
MyBatis可以通過簡單的XML或者注解來配置和映射原始類型,接口,和Java POJO為數(shù)據(jù)庫中記錄,使用MyBatis幫助我們解決各種問題,本文介紹如何在Spring?Boot中使用MyBatis訪問數(shù)據(jù)庫,感興趣的朋友一起看看吧2023-11-11
簡單聊一聊Java線程池ThreadPoolExecutor
在使用線程池之后,開啟線程就變成了在線程池當(dāng)中找到一個空閑的線程,銷毀線程變成了歸還線程到線程池的過程,下面這篇文章主要給大家介紹了關(guān)于Java線程池ThreadPoolExecutor的相關(guān)資料,需要的朋友可以參考下2022-06-06
Springboot使用redisson?+?自定義注解實現(xiàn)消息的發(fā)布訂閱(解決方案)
Redisson是一個基于Redis的Java駐留內(nèi)存數(shù)據(jù)網(wǎng)格(In-Memory?Data?Grid)和分布式鎖框架,它提供了一系列的分布式Java對象和服務(wù),可以幫助開發(fā)者更方便地使用Redis作為數(shù)據(jù)存儲和分布式鎖的解決方案,感興趣的朋友跟隨小編一起看看吧2024-05-05
springboot實現(xiàn)rabbitmq消息確認(rèn)的示例代碼
RabbitMQ的消息確認(rèn)有兩種, 一種是消息發(fā)送確認(rèn),第二種是消費(fèi)接收確認(rèn),本文主要介紹了springboot實現(xiàn)rabbitmq消息確認(rèn)的示例代碼,具有一定的參考價值,感興趣的可以了解一下2023-09-09

