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

