submit

更新时间:2022-12-31 22:48:49 阅读: 评论:0


2022年12月31日发(作者:广西教育培训网在线培训系统)

ThreadPoolExecutor中的submit()⽅法详细讲解

ThreadPoolExecutor中的submit()⽅法详细讲解

在使⽤线程池的时候,发现除了execute()⽅法可以执⾏任务外,还发现有⼀个⽅法submit()可以执⾏任务。

submit()有3个参数不⼀的⽅法,这些⽅法都是在ExecutorService接⼝中声明的,在AbstractExecutorService中实现,⽽ThreadPoolExecutor继

承AbstractExecutorService。

我们可以看到submit()的参数既可以是Runnable,⼜可以是Callable。对于Runnable我们是⽐较熟的,它是线程Thread所执⾏的任务,⾥

⾯有⼀个run()⽅法,是任务的具体执⾏操作。那么Callable呢?我们⼀起看下他们的代码吧。

Runnable这⾥就不介绍了,Callable接⼝定义了⼀个call()⽅法,返回⼀个Callable指定的泛型类,并且call()调⽤的时候会抛出异常。通过

⽐较Runnable和Callable还看不什么端倪,那么我们就看看内部实现吧。

submmit()参数解析

这⾥重点分析submit()带参数Runnable和Callable的⽅法

我们发现2者的实现没有任何的差异,唯⼀就是submit()参数不同。

参数传⼊newTaskFor()⽅法,那么可以肯定就是在这个⽅法⾥做了什么操作。

Futuresubmit(Callablecallable);

Futuresubmit(Runnablevar1,Tresult);

Future<?>submit(Runnablerunnable);

publicinterfaceRunnable{

voidrun();

}

publicinterfaceCallable{

Vcall()throwsException;

}

publicFuture<?>submit(Runnabletask){

if(task==null)thrownewNullPointerException();

RunnableFutureftask=newTaskFor(task,null);

execute(ftask);

returnftask;

}

publicFuturesubmit(Callabletask){

if(task==null)thrownewNullPointerException();

RunnableFutureftask=newTaskFor(task);

execute(ftask);

returnftask;

}

protectedRunnableFuturenewTaskFor(Runnablerunnable,Tvalue){

returnnewFutureTask(runnable,value);

}

protectedRunnableFuturenewTaskFor(Callablecallable){

returnnewFutureTask(callable);

}

newTaskFor()的⽬的就是创建⼀个FutureTask对象,那我们追踪到FutureTask的构造⽅法(FutureTask⾮常关键,后⾯会分析)。

到了这⾥我们知道,其实Runnable会在这⾥转化成Callable。我们来看下le()具体实现。

le()创建了⼀个RunnableAdapter对象,RunnableAdapter实现了Callable接⼝,在call()⽅法中调⽤了传⼊

的Runnable的run(),并且将传⼊的result参数返回。

也就是说我们调⽤submit()传⼊的Runnbale最终会转化成Callable,并且返回⼀个result值(如果我们传⼊这个参数则返回这个参数,不传⼊

则返回null)。

到这⾥我们讲清楚了submit()的参数的区别和内部实现,submit()⽅法有⼀个返回值Future,下⾯我们来分析⼀下返回值Future。

submit()的返回值Future

上⾯分析submit()源码可知,submit()返回的是⼀个RunnableFuture类对象,真正是通过newTaskFor()⽅法返回⼀个newFutureTask()对象。

所以submit()返回的真正的对象是FutureTask对象。

那么FutureTask是什么,我们来看下它的类继承关系。

通过继承关系我们可以明确的知道其实FutureTask就是⼀个Runnable。并且有⾃⼰run()实现。我们来看下FutureTask的run()是如何实现

的。

publicFutureTask(Runnablerunnable,Vresult){

le=le(runnable,result);

=NEW;

}

publicFutureTask(Callablecallable){

if(callable==null)thrownewNullPointerException();

le=callable;

=NEW;

}

publicstaticCallablecallable(Runnabletask,Tresult){

if(task==null)

thrownewNullPointerException();

returnnewRunnableAdapter(task,result);

}

privatestaticfinalclassRunnableAdapterimplementsCallable{

privatefinalRunnabletask;

privatefinalTresult;

RunnableAdapter(Runnabletask,Tresult){

=task;

=result;

}

publicTcall(){

();

returnresult;

}

}

publicclassFutureTaskimplementsRunnableFuture{

...

}

publicinterfaceRunnableFutureextendsRunnable,Future{

voidrun();

}

我们在newFutureTask()对象的时候,在FutureTask构造⽅法中会对state状态赋值为NEW,并且传⼊⼀个callable对象。通

过FutureTask的run()我们可以知道,其实就通过state状态判断,调⽤callable的call()。(如果传⼊的参数

是Runnable,Runnable在RunnableAdapter类中转化时,在call()中,其实调⽤的就是Runnable的run()⽅法)。

所以在submit()⽅法中,调⽤了⼀个execute(task)的⽅法,实际执⾏的是FutureTask的run(),⽽FutureTask的run()调⽤的

是Callable的call()⽅法。

说了这么多,submit()最后执⾏的还是传⼊的Runnable的run()或Callable的call()⽅法。好像没有FutureTask什么事啊。

其实不是,submit()返回FutureTask对象,通过这个FutureTask对象调⽤get()可以返回submit()⽅法传⼊的⼀个泛型类参数result对象,如

果是Callable直接通过call()返回。这个返回值的可以⽤来校验任务执⾏是否成功。

FutureTask的get()的实现

publicvoidrun(){

if(state!=NEW||

!eAndSwapObject(this,RUNNER,null,tThread()))

return;

try{

Callablec=callable;

if(c!=null&&state==NEW){

Vresult;

booleanran;

try{

result=();

ran=true;

}catch(Throwableex){

result=null;

ran=fal;

tException(ex);

}

if(ran)

t(result);

}

}finally{

//runnermustbenon-nulluntilstateisttledto

//preventconcurrentcallstorun()

runner=null;

//statemustbere-readafternullingrunnertoprevent

//leakedinterrupts

ints=state;

if(s>=INTERRUPTING)

handlePossibleCancellationInterrupt(s);

}

}

publicVget()throwsInterruptedException,ExecutionException{

ints=state;

if(s<=COMPLETING)

s=awaitDone(fal,0L);//等待任务执⾏完

returnreport(s);//将执⾏的任务结果返回

}

privateVreport(ints)throwsExecutionException{

Objectx=outcome;

if(s==NORMAL)

return(V)x;

if(s>=CANCELLED)

thrownewCancellationException();

thrownewExecutionException((Throwable)x);

}

最后是通过outcome参数将根据任务的状态将结果返回。那么outcome参数在哪⾥赋值了?outcome参数赋值的地⽅有好2处,⼀

是FutureTask的t(),⼆是FutureTask的tException()。

t()是在FutureTask的run()执⾏完成后,将传⼊的result参数赋值给传⼊给t(),赋值给outcome参数。如果run()报异常了会

将Throwable对象通过tException()⽅法传⼊,赋值给outcome变量

⼤家可以返回上⾯的run()查看下。

submit()使⽤案例

打印结果:

protectedvoidt(Vv){

if(eAndSwapInt(this,STATE,NEW,COMPLETING)){

outcome=v;

eredInt(this,STATE,NORMAL);//finalstate

finishCompletion();

}

}

protectedvoidtException(Throwablet){

if(eAndSwapInt(this,STATE,NEW,COMPLETING)){

outcome=t;

eredInt(this,STATE,EXCEPTIONAL);//finalstate

finishCompletion();

}

}

publicclassTest{

privatestaticfinalStringSUCCESS="success";

publicstaticvoidmain(String[]args){

ExecutorServiceexecutorService=edThreadPool(3);

n("------------------任务开始执⾏---------------------");

Futurefuture=(newCallable(){

@Override

publicStringcall()throwsException{

(5000);

n("submit⽅法执⾏任务完成"+"threadname:"+tThread().getName());

returnSUCCESS;

}

});

try{

Strings=();

if((s)){

Stringname=tThread().getName();

n("经过返回值⽐较,submit⽅法执⾏任务成功threadname:"+name);

}

}catch(InterruptedExceptione){

tackTrace();

}catch(ExecutionExceptione){

tackTrace();

}

n("-------------------mainthreadend---------------------");

}

}

主线程会⼀直阻塞,等待线程池中的任务执⾏完后,在执⾏后⾯的语句。

------------------任务开始执⾏---------------------

call()调⽤开始:82

submit⽅法执⾏任务完成:97threadname:pool-1-thread-1

经过返回值⽐较,submit⽅法执⾏任务成功threadname:main

-------------------mainthreadend---------------------

本文发布于:2022-12-31 22:48:49,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/90/68311.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:就教的意思
下一篇:valid
标签:submit
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图