最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中Runnable和Callable分別什么時候使用

 更新時間:2023年08月07日 15:03:26   作者:古時的風(fēng)箏  
提到 Java 就不得不說多線程了,就算你不想說,面試官也得讓你說呀,那說到線程,就不得不說Runnable和Callable這兩個家伙了,二者在什么時候使用呢,下面就來和簡單講講

提到 Java 就不得不說多線程了,就算你不想說,面試官也得讓你說呀,對不對。那說到多線程,就不得提線程了(這不廢話嗎)。那說到線程,就不得不說RunnableCallable這兩個家伙了。

說熟悉也是真熟悉,在剛學(xué)習(xí)多線程的時候,第一個例子大概就是下面這樣子的。

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("執(zhí)行線程" + Thread.currentThread().getName());
    }
}).start();

看到了 Runnable的身影,有時候還會看到Callable的。

但是說很熟悉吧,印象也不是很大,好像就用了一下這兩位的名號,然后剩下的部分就跟他倆沒啥關(guān)系了。

今天,我們就來看看這兩位到底是什么,有什么區(qū)別,什時候應(yīng)該用 Runnable,什么時候又應(yīng)該用 Callable。

Runnable

自從Java誕生,Runnable就存在了,元老中的元老了,在 1.5之前,如果你想使用線程,那必須要實現(xiàn)自 Runnable。因為到了 JDK1.5,JDK 才加入了Callable。

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

是不是接口非常簡單,就一個抽象方法。

其實還可以再簡化一下, @FunctionalInterface標(biāo)明這個接口是一個函數(shù)式接口。函數(shù)式接口是在 JDK8才加入的,為的就是實現(xiàn)函數(shù)式編程,就那種Lambada表達式。

所以在 JDK1.7中,是沒有@FunctionalInterface修飾的,簡簡單單。我們找到 JDK1.7的 Ruunable實現(xiàn),是下面這樣子

public interface Runnable {
    public abstract void run();
}

想了解更多函數(shù)式編程的話,可以看這篇文章:Lambda、函數(shù)式接口、Stream 一次性全給你

如果一個線程類要實現(xiàn) Runnable 接口,則這個類必須定義一個名為 run 的無參數(shù)方法。

實現(xiàn)了 Runnable 接口的類可以通過實例化一個 Thread 實例,并將自身作為目標(biāo)傳遞來運行。

舉個例子

首先定義一個RunnableThread類,并實現(xiàn)自(implements)Runnable接口,然后重寫 run方法。

public class RunnableThread implements Runnable{
    @Override
    public void run() {
        System.out.println("當(dāng)前線程名稱"+ Thread.currentThread().getName());
    }
}

使用RunnableThread作為線程類(Thread)實例化的參數(shù),然后調(diào)用run方法。

RunnableThread runnableThread = new RunnableThread();
Thread thread = new Thread(runnableThread);
thread.start();

注意,是調(diào)用新 new 出來的 Thread 實例的start() 方法,不要調(diào)用run方法,雖然我們是重寫Runnablerun方法的。調(diào)用 run方法并沒有創(chuàng)建線程的效果,而是直接在當(dāng)前線程執(zhí)行,就和執(zhí)行一個普通類的普通方法一模一樣。

為什么要調(diào)用 start()方法呢,我們看看 Threadstart()方法實現(xiàn)中,其實是調(diào)用了一個名稱為 start0()的 native 方法,native 方法就不是用 Java 實現(xiàn)的了,而是在 JVM 層面的實現(xiàn)。

這個start0方法的主要邏輯就是啟動一個操作系統(tǒng)線程,并和 JVM 線程綁定,開辟一些空間來存儲線程狀態(tài)和上下文的數(shù)據(jù),然后執(zhí)行綁定的 JVM 線程(也就是我們實現(xiàn)了Runnable的類)的 run方法的代碼塊,從而執(zhí)行我們自定義的邏輯。

還可以用線程池的方式調(diào)用

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
        .setNameFormat("thread-pool-%d").build();
ExecutorService singleThreadPool = new ThreadPoolExecutor(1, 1,
        0L, TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
singleThreadPool.execute(runnableThread);
singleThreadPool.shutdown();

如果 Runnable那么完美的話,就沒必要在 JDK1.5中加入和它超級相似的 Callable了。

Runnable有什么不完美的地方嗎?就是它的 run方法是沒有返回值的。

如果你想在主線程中拿到新開啟線程的返回值的話,Runnable就不太方便了。必須要借助共享變量來完成。

所以,如果你的場景是要有返回值的話, 就要 Callable出手了。

Callable

Callable是在 JDK1.5才加入的,為的就是彌補 Runnable沒有返回值的缺陷,雖然絕大多數(shù)場景都可以用 Runnable來實現(xiàn)。

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

Runnable類似的,@FunctionalInterface也是后來加入的,可以不考慮,只是為了函數(shù)式寫法。

Callable接口只有一個 call方法,并且有一個泛型返回值,可以返回任何類型。

舉個例子

首先聲明一個類,實現(xiàn)自 Callable接口,返回值為字符串類型

public class CallableThread implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "線程名稱:" + Thread.currentThread().getName();
    }
}

在代碼中通過下面的方式調(diào)用

CallableThread callableThread = new CallableThread();
FutureTask<String> futureTask = new FutureTask<>(callableThread);
Thread thread = new Thread(futureTask);
thread.start();
String result = futureTask.get();
System.out.println("執(zhí)行結(jié)果= " + result);

看上去就比 Runnable要復(fù)雜一點,要借助FutureTask了,因為 Thread類沒有接受Callable的構(gòu)造函數(shù)。

使用 FutureTask.get()方法獲取執(zhí)行結(jié)果。

在日常的開發(fā)中,不建議直接這樣用,除非你明確的知道這樣做沒有問題,否則的話,推薦使用線程池的方式來使用。

CallableThread callableThread = new CallableThread();
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(callableThread);
String result = future.get();
System.out.println("任務(wù)執(zhí)行結(jié)果: " + result);
executor.shutdown();

如何選擇用哪一個

取舍的基本原則就是需不需要返回值,如果不需要返回值,那直接就選 Runnable,不用猶豫。如果有返回值的話,那更不用猶豫,不要想著借助共享變量的方式。

另外還有一點就是是否需要拋出異常, Runnable是不接受拋出異常的,Callable可以拋出異常。

Runnable適合那種純異步的處理邏輯。比如每天定時計算報表,將報表存儲到數(shù)據(jù)庫或者其他地方,只是要計算,不需要馬上展示,展示內(nèi)容是在其他的方法中單獨獲取的。

比如那些非核心的功能,當(dāng)核心流程執(zhí)行完畢后,非核心功能就自己去執(zhí)行吧,至于成不成功的,不是特別重要。例如一個購物下單流程,下單、減庫存、加到用戶的訂單列表、扣款是核心功能,之后的發(fā)送APP通知、短信通知這些就啟動新線程去干去吧。

最后

Runnablejava.lang這個包下,而當(dāng)JDK1.5發(fā)布的時候,新加入的 Callable被安置在了 java.util.concurrent這個包下,這是 Java 里有名的并發(fā)編程相關(guān)包,各種鎖啊、多線程工具類啊,都被放在這個包下。按道理,Runnable 也應(yīng)該在這里才對。

可見再厲害的項目也是隨著項目的擴大而慢慢的規(guī)劃,而前期的一些看似不太合理的地方,只能做兼容和妥協(xié)。

到此這篇關(guān)于Java中Runnable和Callable分別什么時候使用的文章就介紹到這了,更多相關(guān)Java Runnable Callable內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實現(xiàn)樹形菜單的方法總結(jié)

    Java實現(xiàn)樹形菜單的方法總結(jié)

    當(dāng)我們想要展示層級結(jié)構(gòu),如文件目錄、組織結(jié)構(gòu)或分類目錄時,樹形菜單是一個直觀且有效的解決方案,本文為大家整理了java中幾種常見方法,希望對大家有所幫助
    2023-08-08
  • 手把手教你實現(xiàn)Java第三方應(yīng)用登錄

    手把手教你實現(xiàn)Java第三方應(yīng)用登錄

    本文主要介紹了手把手教你實現(xiàn)Java第三方應(yīng)用登錄,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 詳細聊一聊Java中的包機制

    詳細聊一聊Java中的包機制

    這篇文章主要介紹了Java中包機制的相關(guān)資料,Java包機制通過定義、命名和組織類,防止命名沖突,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-05-05
  • IDEA的TODO的使用方式

    IDEA的TODO的使用方式

    這篇文章主要介紹了IDEA的TODO的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringBoot集成SpringSecurity和JWT做登陸鑒權(quán)的實現(xiàn)

    SpringBoot集成SpringSecurity和JWT做登陸鑒權(quán)的實現(xiàn)

    這篇文章主要介紹了SpringBoot集成SpringSecurity和JWT做登陸鑒權(quán)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Java面試必備八股文整理

    Java面試必備八股文整理

    這篇文章主要介紹了Java面試必備八股文整理,小伙伴們出去面試的時候會被問到很多java專業(yè)性的知識,那么八股文就是為此而出現(xiàn)的,需要的朋友可以參考下
    2023-03-03
  • Java8如何將Array轉(zhuǎn)換為Stream的實現(xiàn)代碼

    Java8如何將Array轉(zhuǎn)換為Stream的實現(xiàn)代碼

    這篇文章主要介紹了Java8如何將Array轉(zhuǎn)換為Stream的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 結(jié)合Mybatis聊聊對SQL注入的見解

    結(jié)合Mybatis聊聊對SQL注入的見解

    這篇文章主要介紹了結(jié)合Mybatis聊聊對SQL注入的見解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java對象初始化代碼詳解

    java對象初始化代碼詳解

    這篇文章主要介紹了java對象初始化代碼詳解,涉及實例變量的初始化,類變量的初始化等相關(guān)介紹幾代碼示例,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • java 中 zookeeper簡單使用

    java 中 zookeeper簡單使用

    ZooKeeper是一個分布式的,開放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Google的Chubby一個開源的實現(xiàn),是Hadoop和Hbase的重要組件。下面通過本文給大家分享java 中 zookeeper簡單使用,需要的朋友參考下吧
    2017-09-09

最新評論

马龙县| 花垣县| 礼泉县| 甘南县| 商城县| 平谷区| 鄂托克旗| 巢湖市| 漯河市| 扶沟县| 安平县| 中宁县| 洛南县| 台南县| 堆龙德庆县| 丹阳市| 和静县| 新干县| 内江市| 班玛县| 洞口县| 若羌县| 丹江口市| 手机| 龙岩市| 义马市| 莱西市| 泰和县| 嘉鱼县| 旬阳县| 泾阳县| 安康市| 遂宁市| 政和县| 海伦市| 娱乐| 泌阳县| 珠海市| 巴林右旗| 施秉县| 宝清县|