欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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 實(shí)戰(zhàn)范例之精美網(wǎng)上音樂(lè)平臺(tái)的實(shí)現(xiàn)

    Java 實(shí)戰(zhàn)范例之精美網(wǎng)上音樂(lè)平臺(tái)的實(shí)現(xiàn)

    讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+vue+Springboot+ssm+mysql+maven+redis實(shí)現(xiàn)一個(gè)前后端分離的精美網(wǎng)上音樂(lè)平臺(tái),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • springboot2.0整合logback日志的詳細(xì)代碼

    springboot2.0整合logback日志的詳細(xì)代碼

    這篇文章主要介紹了springboot2.0整合logback日志的應(yīng)用場(chǎng)景分析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • SpringBoot集成tomcat詳解實(shí)現(xiàn)過(guò)程

    SpringBoot集成tomcat詳解實(shí)現(xiàn)過(guò)程

    采用spring boot之后,一切變得如此簡(jiǎn)單,打包->java-jar->運(yùn)維,只需要一個(gè)jar包便可以隨意部署安裝。這篇文章,將對(duì) spring boot集成tomcat的源碼進(jìn)行分析,探索其內(nèi)部的原理
    2023-02-02
  • 使用Spring CROS解決項(xiàng)目中的跨域問(wèn)題詳解

    使用Spring CROS解決項(xiàng)目中的跨域問(wèn)題詳解

    這篇文章主要介紹了使用Spring CROS解決項(xiàng)目中的跨域問(wèn)題詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Java拆箱與裝箱實(shí)例詳解

    Java拆箱與裝箱實(shí)例詳解

    這篇文章主要介紹了Java拆箱與裝箱,結(jié)合實(shí)例形式詳細(xì)分析了Java拆箱與裝箱相關(guān)的數(shù)據(jù)類型轉(zhuǎn)換操作技巧,需要的朋友可以參考下
    2019-11-11
  • JDK8新特性之判空遍歷寫法

    JDK8新特性之判空遍歷寫法

    這篇文章主要介紹了JDK8新特性之判空遍歷寫法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?'xxx'的解決辦法

    MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?&a

    這篇文章主要給大家介紹了關(guān)于MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?'xxx'的解決辦法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Spring Boot 中的靜態(tài)資源放置位置

    Spring Boot 中的靜態(tài)資源放置位置

    這篇文章主要介紹了Spring Boot 中的靜態(tài)資源到底要存放哪里,很多童鞋對(duì)這個(gè)問(wèn)題很糾結(jié),接下來(lái)通過(guò)本文給大家介紹下,需要的朋友可以參考下
    2019-04-04
  • java基礎(chǔ)的詳細(xì)了解第四天

    java基礎(chǔ)的詳細(xì)了解第四天

    這篇文章對(duì)Java編程語(yǔ)言的基礎(chǔ)知識(shí)作了一個(gè)較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考,希望能給你帶來(lái)幫助
    2021-08-08
  • SpringBoot實(shí)現(xiàn)發(fā)送郵件任務(wù)

    SpringBoot實(shí)現(xiàn)發(fā)送郵件任務(wù)

    這篇文章主要為大家詳細(xì)介紹了SpringBoot實(shí)現(xiàn)發(fā)送郵件任務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02

最新評(píng)論