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

java Callable接口和Future接口創(chuàng)建線程示例詳解

 更新時間:2023年11月23日 09:35:25   作者:長名06  
這篇文章主要為大家介紹了java Callable接口和Future接口創(chuàng)建線程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Callable接口和Future接口

創(chuàng)建線程的方式

1.繼承Thread類2.實(shí)現(xiàn)Runnable接口3.Callable接口4.線程池方式

Callable接口

在繼承Thread類和實(shí)現(xiàn)Runnable接口的方式創(chuàng)建線程時,線程執(zhí)行的run方法中,返回值是void,即無法返回線程的執(zhí)行結(jié)果,為了支持該功能,java提供了Callable接口。

Callable和Runnable接口的區(qū)別

  • 1.Callable中的call()方法,可以返回值,Runnable接口中的run方法,無返回值(void)。
  • 2.call()方法可以拋出異常,run()不能拋異常。
  • 3.實(shí)現(xiàn)Callable接口,必須重寫call()方法,run是抽象方法,抽象類可以不實(shí)現(xiàn)。
  • 4.不能用Callable接口的對象,直接替換Runnable接口對象,創(chuàng)建線程。

Future接口

當(dāng)call()方法完成時,結(jié)果必須存儲在主線程已知的對象中,以便主線程可以知道線程返回的結(jié)果,可以使用Future對象。將Future視為保存結(jié)果的對象-該對象,不一定會將call接口返回值,保存到主線程中,但是會持有call返回值。Future基本上是主線程可以跟蹤以及其他線程的結(jié)果的一種方式。要實(shí)現(xiàn)此接口,必須重寫5個方法。

public interface Future<V> {//Future源碼
    /**
     * Attempts to cancel execution of this task.  This attempt will
     * fail if the task has already completed, has already been cancelled,
     * or could not be cancelled for some other reason. If successful,
     * and this task has not started when {@code cancel} is called,
     * this task should never run.  If the task has already started,
     * then the {@code mayInterruptIfRunning} parameter determines
     * whether the thread executing this task should be interrupted in
     * an attempt to stop the task.
     *
     * <p>After this method returns, subsequent calls to {@link #isDone} will
     * always return {@code true}.  Subsequent calls to {@link #isCancelled}
     * will always return {@code true} if this method returned {@code true}.
     *
     * @param mayInterruptIfRunning {@code true} if the thread executing this
     * task should be interrupted; otherwise, in-progress tasks are allowed
     * to complete
     * @return {@code false} if the task could not be cancelled,
     * typically because it has already completed normally;
     * {@code true} otherwise
     */
    boolean cancel(boolean mayInterruptIfRunning);
    //用于停止任務(wù),如果未啟動,將停止任務(wù),已啟動,僅在mayInterrupt為true時才會中斷任務(wù)
    /**
     * Returns {@code true} if this task was cancelled before it completed
     * normally.
     *
     * @return {@code true} if this task was cancelled before it completed
     */
    boolean isCancelled();
    /**
     * Returns {@code true} if this task completed.
     *
     * Completion may be due to normal termination, an exception, or
     * cancellation -- in all of these cases, this method will return
     * {@code true}.
     *
     * @return {@code true} if this task completed
     */
    boolean isDone();//判斷任務(wù)是否完成,完成true,未完成false
    /**
     * Waits if necessary for the computation to complete, and then
     * retrieves its result.
     *
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     */
    V get() throws InterruptedException, ExecutionException;//任務(wù)完成返回結(jié)果,未完成,等待完成
    /**
     * Waits if necessary for at most the given time for the computation
     * to complete, and then retrieves its result, if available.
     *
     * @param timeout the maximum time to wait
     * @param unit the time unit of the timeout argument
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     * @throws TimeoutException if the wait timed out
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Callable和Future是分別做各自的事情,Callable和Runnable類似,因?yàn)樗庋b了要在另一個線程上允許的任務(wù),而Future用于存儲從另一個線程獲取的結(jié)果。實(shí)際上,F(xiàn)uture和Runnable可以一起使用。創(chuàng)建線程需要Runnable,為了獲取結(jié)果,需要Future。

FutureTask

Java庫本身提供了具體的FutureTask類,該類實(shí)現(xiàn)了Runnable和Future接口,并方便的將兩種功能組合在一起。并且其構(gòu)造函數(shù)提供了Callable來創(chuàng)建FutureTask對象。然后將該FutureTask對象提供給Thread的構(gòu)造函數(shù)以創(chuàng)建Thread對象。因此,間接的使用Callable創(chuàng)建線程。

關(guān)于FutureTask構(gòu)造函數(shù)的理解

public class FutureTask<V> implements RunnableFuture<V> {//實(shí)現(xiàn)了RunnableFuture
	//該類的構(gòu)造函數(shù)有兩個
    public FutureTask(Callable<V> callable) {//
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
    //用此方法創(chuàng)建的線程,最后start()調(diào)用的其實(shí)是Executors.RunnableAdapter類的call(); 
    public FutureTask(Runnable runnable, V result) {//返回的結(jié)果,就是構(gòu)造函數(shù)傳入的值
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }
    //原因如下
    //使用FutureTask對象的方式,創(chuàng)建的Thread,在開啟線程.start后,底層執(zhí)行的是
   //Thread的方法 start()方法會調(diào)用start0(),但是調(diào)用這個start0()(操作系統(tǒng)創(chuàng)建線程)的時機(jī),是操作系統(tǒng)決定的,但是這個start0()最后會調(diào)用run()方法,此線程的執(zhí)行內(nèi)容就在傳入的對象的run()方法中
    public void run() {
        if (target != null) {
            target.run();
            //執(zhí)行到這 target就是在創(chuàng)建Thread時,傳遞的Runnable接口的子類對象,F(xiàn)UtureTask方式就是傳入的FutureTask對象
            //會執(zhí)行FutureTask中的run()方法
        }
    }
    //FutureTask的run()
    public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;//類的屬性
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    //會執(zhí)行callable的call(),callable是創(chuàng)建TutureTask時,根據(jù)傳入的Runnable的對象封裝后的一個對象
                    //this.callable = Executors.callable(runnable, result);
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
    //Executors類的callable
    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }
    //最后執(zhí)行到這里 Executors類的靜態(tài)內(nèi)部類RunnableAdapter
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }
}
public interface RunnableFuture<V> extends Runnable, Future<V> {//繼承了Runnable, Future<V>接口
	void run();//
}

使用FutureTask類間接的用Callable接口創(chuàng)建線程

/**
 * @author 長名06
 * @version 1.0
 * 演示Callable創(chuàng)建線程 需要使用到Runnable的實(shí)現(xiàn)類FutureTask類
 */
public class CallableDemo {
    public static void main(String[] args) {
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() +  "使用Callable接口創(chuàng)建的線程");
            return 100;
        });
        new Thread(futureTask,"線程1").start();
    }
}

核心原理

在主線程中需要執(zhí)行耗時的操作時,但不想阻塞主線程,可以把這些作業(yè)交給Future對象來做。

  • 1.主線程需要,可以通過Future對象獲取后臺作業(yè)的計算結(jié)果或者執(zhí)行狀態(tài)。
  • 2.一般FutureTask多用于耗時的計算,主線程可以在完成自己的任務(wù)后,再獲取結(jié)果。
  • 3.只有執(zhí)行完后,才能獲取結(jié)果,否則會阻塞get()方法。
  • 4.一旦執(zhí)行完后,不能重新開始或取消計算。get()只會計算一次

小結(jié)

  • 1.在主線程需要執(zhí)行比較耗時的操作時,但又不想阻塞主線程,可以把這些作業(yè)交給Future對象在后臺完成,當(dāng)主線程將來需要時,就可以通過Future對象獲得后臺作業(yè)的計算結(jié)果或者執(zhí)行狀態(tài)。
  • 2.一般FutureTask多用于耗時的計算,主線程可以在完成自己的任務(wù)后,再去獲取結(jié)果。
  • 3.get()方法只能獲取結(jié)果,并且只能計算完后獲取,否則會一直阻塞直到任務(wù)轉(zhuǎn)入完成狀態(tài),然后會返回結(jié)果或拋出異常。且只計算一次,計算完成不能重新開始或取消計算。

以上就是java Callable接口和Future接口創(chuàng)建線程示例詳解的詳細(xì)內(nèi)容,更多關(guān)于java Callable Future接口創(chuàng)建線程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用Java實(shí)現(xiàn)文件流轉(zhuǎn)base64

    使用Java實(shí)現(xiàn)文件流轉(zhuǎn)base64

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)文件流轉(zhuǎn)base64效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • Java SpringBoot實(shí)現(xiàn)文件上傳功能的示例代碼

    Java SpringBoot實(shí)現(xiàn)文件上傳功能的示例代碼

    這篇文章主要介紹了如何利用Java SpringBoot實(shí)現(xiàn)文件上傳功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)有一定幫助,需要的可以參考一下
    2022-03-03
  • Spring Boot 整合 Mybatis Annotation 注解的完整 Web 案例

    Spring Boot 整合 Mybatis Annotation 注解的完整 Web 案例

    這篇文章主要介紹了Spring Boot 整合 Mybatis Annotation 注解的完整 Web 案例,需要的朋友可以參考下
    2017-05-05
  • Maven 集成 groovy 腳本插件gmavenplus-plugin詳解

    Maven 集成 groovy 腳本插件gmavenplus-plugin詳解

    文章介紹了在Maven構(gòu)建過程中使用Groovy腳本進(jìn)行動態(tài)配置的示例,重點(diǎn)解析了如何在`<build>`配置片段中綁定腳本到`initialize`生命周期階段,并詳細(xì)說明了腳本執(zhí)行流程、常見使用場景以及潛在問題和優(yōu)化建議,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • java書店系統(tǒng)畢業(yè)設(shè)計 用戶模塊(2)

    java書店系統(tǒng)畢業(yè)設(shè)計 用戶模塊(2)

    這篇文章主要介紹了java書店系統(tǒng)畢業(yè)設(shè)計,第二步系統(tǒng)總體設(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • JAVA正則表達(dá)式匹配多個空格的解決方案

    JAVA正則表達(dá)式匹配多個空格的解決方案

    這篇文章主要介紹了JAVA正則表達(dá)式匹配多個空格的解決方案,文中提到了()和[]本質(zhì)的區(qū)別,本文給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-11-11
  • 多線程死鎖的產(chǎn)生以及如何避免死鎖方法(詳解)

    多線程死鎖的產(chǎn)生以及如何避免死鎖方法(詳解)

    下面小編就為大家?guī)硪黄嗑€程死鎖的產(chǎn)生以及如何避免死鎖方法(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • SpringMVC獲取請求參數(shù)的方法詳解

    SpringMVC獲取請求參數(shù)的方法詳解

    這篇文章主要為大家詳細(xì)介紹了SpringMVC中獲取請求參數(shù)的方法,例如通過ServletAPI獲取和通過控制器方法的形參獲取請求參數(shù)等,需要的可以參考下
    2023-07-07
  • 在Java中使用Jwt的示例代碼

    在Java中使用Jwt的示例代碼

    這篇文章主要介紹了在Java中使用Jwt的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • springboot上傳文件過大的500異常解決

    springboot上傳文件過大的500異常解決

    這篇文章主要介紹了springboot上傳文件過大的500異常解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09

最新評論

巴楚县| 离岛区| 高淳县| 息烽县| 阳泉市| 聊城市| 喀喇沁旗| 玉树县| 哈密市| 九龙坡区| 社旗县| 泊头市| 道孚县| 贡嘎县| 永州市| 航空| 手机| 德格县| 双流县| 合作市| 沂水县| 通州区| 禹城市| 辽宁省| 仙居县| 天门市| 会宁县| 康保县| 房山区| 工布江达县| 大石桥市| 宝清县| 扬中市| 井陉县| 天全县| 田林县| 水富县| 库伦旗| 弥勒县| 黑龙江省| 红原县|