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

ThreadPoolExecutor中的submit()方法詳細(xì)講解

 更新時(shí)間:2022年04月22日 09:51:19   作者:張行之  
在使用線程池的時(shí)候,發(fā)現(xiàn)除了execute()方法可以執(zhí)行任務(wù)外,還發(fā)現(xiàn)有一個(gè)方法submit()可以執(zhí)行任務(wù),本文就詳細(xì)的介紹一下ThreadPoolExecutor中的submit()方法,具有一定的參考價(jià)值,感興趣的可以了解一下

在使用線程池的時(shí)候,發(fā)現(xiàn)除了execute()方法可以執(zhí)行任務(wù)外,還發(fā)現(xiàn)有一個(gè)方法submit()可以執(zhí)行任務(wù)。

submit()有3個(gè)參數(shù)不一的方法,這些方法都是在ExecutorService接口中聲明的,在AbstractExecutorService中實(shí)現(xiàn),而ThreadPoolExecutor繼承AbstractExecutorService。

<T> Future<T> submit(Callable<T> callable);
<T> Future<T> submit(Runnable var1, T result);
Future<?> submit(Runnable runnable);

我們可以看到submit()的參數(shù)既可以是Runnable,又可以是Callable。對(duì)于Runnable我們是比較熟的,它是線程Thread所執(zhí)行的任務(wù),里面有一個(gè)run()方法,是任務(wù)的具體執(zhí)行操作。那么Callable呢?我們一起看下他們的代碼吧。

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

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

Runnable這里就不介紹了,Callable接口定義了一個(gè)call()方法,返回一個(gè)Callable指定的泛型類,并且call()調(diào)用的時(shí)候會(huì)拋出異常。通過(guò)比較Runnable和Callable還看不什么端倪,那么我們就看看內(nèi)部實(shí)現(xiàn)吧。

submmit()參數(shù)解析

這里重點(diǎn)分析submit()帶參數(shù)Runnable和Callable的方法

public Future<?> submit(Runnable task) {
? ? if (task == null) throw new NullPointerException();
? ? RunnableFuture<Void> ftask = newTaskFor(task, null);
? ? execute(ftask);
? ? return ftask;
}

public <T> Future<T> submit(Callable<T> task) {
? ? if (task == null) throw new NullPointerException();
? ? RunnableFuture<T> ftask = newTaskFor(task);
? ? execute(ftask);
? ? return ftask;
}

我們發(fā)現(xiàn)2者的實(shí)現(xiàn)沒(méi)有任何的差異,唯一就是submit()參數(shù)不同。

參數(shù)傳入newTaskFor()方法,那么可以肯定就是在這個(gè)方法里做了什么操作。

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
? ? return new FutureTask<T>(runnable, value);
}

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
? ? return new FutureTask<T>(callable);
}

newTaskFor()的目的就是創(chuàng)建一個(gè)FutureTask對(duì)象,那我們追蹤到FutureTask的構(gòu)造方法(FutureTask非常關(guān)鍵,后面會(huì)分析)。

public FutureTask(Runnable runnable, V result) {
? ? this.callable = Executors.callable(runnable, result);
? ? this.state = NEW; ? ? ??
}

public FutureTask(Callable<V> callable) {
? ? if (callable == null)throw new NullPointerException();
? ? this.callable = callable;
? ? this.state = NEW; ? ? ??
}

到了這里我們知道,其實(shí)Runnable會(huì)在這里轉(zhuǎn)化成Callable。我們來(lái)看下Executors.callable()具體實(shí)現(xiàn)。

public static <T> Callable<T> callable(Runnable task, T result) {
? ? if (task == null)
? ? ? ? throw new NullPointerException();
? ? return new RunnableAdapter<T>(task, result);
}

private static final class RunnableAdapter<T> implements Callable<T> {
? ? private final Runnable task;
? ? private final T result;
? ? RunnableAdapter(Runnable task, T result) {
? ? ? ? this.task = task;
? ? ? ? this.result = result;
? ? }
? ? public T call() {
? ? ? ? task.run();
? ? ? ? return result;
? ? }
}

Executors.callable()創(chuàng)建了一個(gè)RunnableAdapter對(duì)象,RunnableAdapter實(shí)現(xiàn)了Callable接口,在call()方法中調(diào)用了傳入的Runnable的run(),并且將傳入的result參數(shù)返回。

也就是說(shuō)我們調(diào)用submit()傳入的Runnbale最終會(huì)轉(zhuǎn)化成Callable,并且返回一個(gè)result值(如果我們傳入這個(gè)參數(shù)則返回這個(gè)參數(shù),不傳入則返回null)。

到這里我們講清楚了submit()的參數(shù)的區(qū)別和內(nèi)部實(shí)現(xiàn),submit()方法有一個(gè)返回值Future,下面我們來(lái)分析一下返回值Future。

submit()的返回值Future

上面分析submit()源碼可知,submit()返回的是一個(gè)RunnableFuture類對(duì)象,真正是通過(guò)newTaskFor()方法返回一個(gè)new FutureTask()對(duì)象。所以submit()返回的真正的對(duì)象是FutureTask對(duì)象。

那么FutureTask是什么,我們來(lái)看下它的類繼承關(guān)系。

public class FutureTask<V> implements RunnableFuture<V> {
? ? ...
}

public interface RunnableFuture<V> extends Runnable, Future<V> {
? ? void run();
}

通過(guò)繼承關(guān)系我們可以明確的知道其實(shí)FutureTask就是一個(gè)Runnable。并且有自己run()實(shí)現(xiàn)。我們來(lái)看下FutureTask的run()是如何實(shí)現(xiàn)的。

public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    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);
        }
    }

我們?cè)趎ew FutureTask()對(duì)象的時(shí)候,在FutureTask構(gòu)造方法中會(huì)對(duì)state狀態(tài)賦值為NEW,并且傳入一個(gè)callable對(duì)象。通過(guò)FutureTask的run()我們可以知道,其實(shí)就通過(guò)state狀態(tài)判斷,調(diào)用callable的call()。(如果傳入的參數(shù)是Runnable,Runnable在RunnableAdapter類中轉(zhuǎn)化時(shí),在call()中,其實(shí)調(diào)用的就是Runnable的run()方法)。

所以在submit()方法中,調(diào)用了一個(gè)execute(task)的方法,實(shí)際執(zhí)行的是FutureTask的run(),而FutureTask的run()調(diào)用的是Callable的call()方法。

說(shuō)了這么多,submit()最后執(zhí)行的還是傳入的Runnable的run()或Callable的call()方法。好像沒(méi)有FutureTask什么事啊。

其實(shí)不是,submit()返回FutureTask對(duì)象,通過(guò)這個(gè)FutureTask對(duì)象調(diào)用get()可以返回submit()方法傳入的一個(gè)泛型類參數(shù)result對(duì)象,如果是Callable直接通過(guò)call()返回。這個(gè)返回值的可以用來(lái)校驗(yàn)任務(wù)執(zhí)行是否成功。

FutureTask的get()的實(shí)現(xiàn)

public V get() throws InterruptedException, ExecutionException {
? ? int s = state;
? ? if (s <= COMPLETING)
? ? ? ? s = awaitDone(false, 0L); ? //等待任務(wù)執(zhí)行完
? ? return report(s);//將執(zhí)行的任務(wù)結(jié)果返回
}


private V report(int s) throws ExecutionException {
? ? Object x = outcome;
? ? if (s == NORMAL)
? ? ? ? return (V)x;
? ? if (s >= CANCELLED)
? ? ? ? throw new CancellationException();
? ? throw new ExecutionException((Throwable)x);
}

最后是通過(guò)outcome參數(shù)將根據(jù)任務(wù)的狀態(tài)將結(jié)果返回。那么outcome參數(shù)在哪里賦值了?outcome參數(shù)賦值的地方有好2處,一是FutureTask的set(),二是FutureTask的setException()。

set()是在FutureTask的run()執(zhí)行完成后,將傳入的result參數(shù)賦值給傳入給set(),賦值給outcome參數(shù)。如果run()報(bào)異常了會(huì)將Throwable對(duì)象通過(guò)setException()方法傳入,賦值給outcome變量

大家可以返回上面的run()查看下。

protected void set(V v) {
? ? if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
? ? ? ? outcome = v;
? ? ? ? U.putOrderedInt(this, STATE, NORMAL); // final state
? ? ? ? finishCompletion();
? ? }
}

protected void setException(Throwable t) {
? ? if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
? ? ? ? outcome = t;
? ? ? ? U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
? ? ? ? finishCompletion();
? ? }
}

submit()使用案例

public class Test {
? ? private static final String SUCCESS = "success";

? ? public static void main(String[] args) {

? ? ? ? ExecutorService executorService = Executors.newFixedThreadPool(3);

? ? ? ? System.out.println("------------------任務(wù)開(kāi)始執(zhí)行---------------------");

? ? ? ? Future<String> future = executorService.submit(new Callable<String>() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public String call() throws Exception {
? ? ? ? ? ? ? ? Thread.sleep(5000);
? ? ? ? ? ? ? ? System.out.println("submit方法執(zhí)行任務(wù)完成" + " ? thread name: " + Thread.currentThread().getName());
? ? ? ? ? ? ? ? return SUCCESS;
? ? ? ? ? ? }
? ? ? ? });

? ? ? ? try {
? ? ? ? ? ? String s = future.get();
? ? ? ? ? ? if (SUCCESS.equals(s)) {
? ? ? ? ? ? ? ? String name = Thread.currentThread().getName();
? ? ? ? ? ? ? ? System.out.println("經(jīng)過(guò)返回值比較,submit方法執(zhí)行任務(wù)成功 ? ?thread name: " + name);
? ? ? ? ? ? }
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (ExecutionException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }

? ? ? ? System.out.println("-------------------main thread end---------------------");
? ? }
}

打印結(jié)果:

------------------任務(wù)開(kāi)始執(zhí)行---------------------
call()調(diào)用開(kāi)始: 1496899867882
submit方法執(zhí)行任務(wù)完成: 1496899872897   thread name: pool-1-thread-1
經(jīng)過(guò)返回值比較,submit方法執(zhí)行任務(wù)成功    thread name: main
-------------------main thread end---------------------

主線程會(huì)一直阻塞,等待線程池中的任務(wù)執(zhí)行完后,在執(zhí)行后面的語(yǔ)句。

到此這篇關(guān)于ThreadPoolExecutor中的submit()方法詳細(xì)講解的文章就介紹到這了,更多相關(guān)ThreadPoolExecutor submit()方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中FileOutputStream流的write方法

    Java中FileOutputStream流的write方法

    這篇文章主要為大家詳細(xì)介紹了Java中FileOutputStream流的write方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • 后端返回各種圖片形式在前端的轉(zhuǎn)換及展示方法對(duì)比

    后端返回各種圖片形式在前端的轉(zhuǎn)換及展示方法對(duì)比

    這篇文章主要給大家介紹了關(guān)于后端返回各種圖片形式在前端的轉(zhuǎn)換及展示方法對(duì)比的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Java中將接口返回的字節(jié)串轉(zhuǎn)為文件詳解

    Java中將接口返回的字節(jié)串轉(zhuǎn)為文件詳解

    這篇文章主要給大家介紹了關(guān)于Java中將接口返回的字節(jié)串轉(zhuǎn)為文件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-11-11
  • RestTemplate調(diào)用POST和GET請(qǐng)求示例詳解

    RestTemplate調(diào)用POST和GET請(qǐng)求示例詳解

    這篇文章主要為大家介紹了RestTemplate調(diào)用POST和GET請(qǐng)求示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Java 在 Word 文檔中使用新文本替換指定文本的方法

    Java 在 Word 文檔中使用新文本替換指定文本的方法

    這篇文章主要介紹了Java 在 Word 文檔中使用新文本替換指定文本的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Java ArrayList.toArray(T[]) 方法的參數(shù)類型是 T 而不是 E的原因分析

    Java ArrayList.toArray(T[]) 方法的參數(shù)類型是 T 而不是 E的原因分析

    這篇文章主要介紹了Java ArrayList.toArray(T[]) 方法的參數(shù)類型是 T 而不是 E的原因分析的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • Java常見(jiàn)的3種文件上傳方法和速度對(duì)比

    Java常見(jiàn)的3種文件上傳方法和速度對(duì)比

    這篇文章介紹了Java常見(jiàn)的3種文件上傳方法和速度對(duì)比,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • SpringCloud搭建Eureka服務(wù)模塊的過(guò)程

    SpringCloud搭建Eureka服務(wù)模塊的過(guò)程

    Eureka在分布式系統(tǒng)中起到了連接各個(gè)微服務(wù)的紐帶作用,使得服務(wù)之間的交互變得更加靈活、可靠,本文將深入探討如何使用Spring?Cloud,逐步引導(dǎo)讀者完成Eureka服務(wù)模塊的搭建,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • gson ajax 數(shù)字精度丟失問(wèn)題的解決方法

    gson ajax 數(shù)字精度丟失問(wèn)題的解決方法

    下面小編就為大家?guī)?lái)一篇gson ajax 數(shù)字精度丟失問(wèn)題的解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • 詳解Spring Security中權(quán)限注解的使用

    詳解Spring Security中權(quán)限注解的使用

    這篇文章主要為大家詳細(xì)介紹一下Spring Security中權(quán)限注解的使用方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以參考一下
    2022-05-05

最新評(píng)論

比如县| 商都县| 利辛县| 崇州市| 垦利县| 南阳市| 芷江| 甘南县| 南溪县| 柞水县| 曲靖市| 西盟| 榆林市| 斗六市| 隆尧县| 聂拉木县| 松滋市| 浦县| 田阳县| 五华县| 宜都市| 杭州市| 温泉县| 合作市| 芒康县| 嫩江县| 山阳县| 靖江市| 大姚县| 宾阳县| 安徽省| 三台县| 栾川县| 新泰市| 雷山县| 肥东县| 习水县| 饶阳县| 武平县| 梁河县| 确山县|