首页 > 试题

furture

更新时间:2022-11-15 20:13:20 阅读: 评论:0

2019南宁中考英语试题-买椟还珠文言文翻译


2022年11月15日发(作者:范曾书法作品欣赏)

Java多线程之FutureTask:带有返回值的函数定义和调⽤⽅式

这篇⽂章主要介绍了Java多线程之FutureTask:带有返回值的函数定义和调⽤⽅式,具有很好的参考价值,希望对⼤家有所帮助。如有错

误或未考虑完全的地⽅,望不吝赐教

FutureTask返回值的函数定义和调⽤

使⽤Runnable接⼝定义的任务是没有返回值的。很多时候,我们是有返回值的,为了解决这个问题,Java提供了Callable接⼝,可以返回

指定类型的值。

但是这个接⼝本⾝是不具备执⾏能⼒的,所以Java中,还有⼀个FutureTask类⽤于使⽤Callable接⼝定义带有返回值的任务。

使⽤⽰例

以下代码演⽰了定义和调⽤的整个过程。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

le;

Task;

publicclassFutureTaskDemo{

publicstaticvoidtest2()throwsExecution{

//基于Lambda的Callable接⼝,在newFutureTask中的Lambda表达式即是Callable接⼝的实现

FutureTasktask=newFutureTask<>(()->{

intt=0;

for(inti=0;i<10;i++)

t+=i;

returnt;

});

//使⽤Thread类执⾏task

n("Startcalling.");

longt1=me();

newThread(task).start();

longresult=();

longt2=me();

n("Finishcalling.");

("Result:%d,Time:%.3fms.n",result,(t2-t1)/1000000f);

}

}

执⾏后的输出:

Startcalling.

Finishcalling.

Result:45,Time:13.620ms.

Java多线程FutureTask⽤法及解析

1FutureTask概念

FutureTask⼀个可取消的异步计算,FutureTask实现了Future的基本⽅法,提空startcancel操作,可以查询计算是否已经完成,并且

可以获取计算的结果。

结果只可以在计算完成之后获取,get⽅法会阻塞当计算没有完成的时候,⼀旦计算已经完成,那么计算就不能再次启动或是取消。

⼀个FutureTask可以⽤来包装⼀个Callable或是⼀个runnable对象。因为FurtureTask实现了Runnable⽅法,所以⼀个FutureTask可

以提交(submit)给⼀个Excutor执⾏(excution).

2FutureTask使⽤场景

FutureTask可⽤于异步获取执⾏结果或取消执⾏任务的场景。

通过传⼊Runnable或者Callable的任务给FutureTask,直接调⽤其run⽅法或者放⼊线程池执⾏,之后可以在外部通过FutureTask的get

⽅法异步获取执⾏结果,因此,FutureTask⾮常适合⽤于耗时的计算,主线程可以在完成⾃⼰的任务后,再去获取结果。

另外,FutureTask还可以确保即使调⽤了多次run⽅法,它都只会执⾏⼀次Runnable或者Callable任务,或者通过cancel取消

FutureTask的执⾏等。

2.1FutureTask执⾏多任务计算的使⽤场景

利⽤FutureTask和ExecutorService,可以⽤多线程的⽅式提交计算任务,主线程继续执⾏其他任务,当主线程需要⼦线程的计算结果

时,在异步获取⼦线程的执⾏结果。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

publicclassFutureTest1{

publicstaticvoidmain(String[]args){

Tasktask=newTask();//新建异步任务

FutureTaskfuture=newFutureTask(task){

//异步任务执⾏完成,回调

@Override

protectedvoiddone(){

try{

n("():"+get());

}catch(InterruptedExceptione){

tackTrace();

}catch(ExecutionExceptione){

tackTrace();

}

}

};

//创建线程池(使⽤了预定义的配置)

ExecutorServiceexecutor=hedThreadPool();

e(future);

try{

(1000);

}catch(InterruptedExceptione1){

tackTrace();

}

//可以取消异步任务

//(true);

try{

//阻塞,等待异步任务执⾏完毕-获取异步任务的返回值

n("():"+());

}catch(InterruptedExceptione){

tackTrace();

}catch(ExecutionExceptione){

tackTrace();

}

}

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

//异步任务

staticclassTaskimplementsCallable{

//返回异步任务的执⾏结果

@Override

publicIntegercall()throwsException{

inti=0;

for(;i<10;i++){

try{

n(tThread().getName()+"_"

+i);

(500);

}catch(InterruptedExceptione){

tackTrace();

}

}

returni;

}

}

}

2.2FutureTask在⾼并发环境下确保任务只执⾏⼀次

在很多⾼并发的环境下,往往我们只需要某些任务只执⾏⼀次。这种使⽤情景FutureTask的特性恰能胜任。

举⼀个例⼦,假设有⼀个带key的连接池,当key存在时,即直接返回key对应的对象;当key不存在时,则创建连接。

对于这样的应⽤场景,通常采⽤的⽅法为使⽤⼀个Map对象来存储key和连接池对应的对应关系,典型的代码如下⾯所⽰:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

privateMapconnectionPool=newHashMap();

privateReentrantLocklock=newReentrantLock();

publicConnectiongetConnection(Stringkey){

try{

();

if(nsKey(key)){

(key);

}

el{

//创建Connection

Connectionconn=createConnection();

(key,conn);

returnconn;

}

}

finally{

();

}

}

21

22

23

24

//创建Connection(根据业务需求,⾃定义Connection)

privateConnectioncreateConnection(){

returnnull;

}

在上⾯的例⼦中,我们通过加锁确保⾼并发环境下的线程安全,也确保了connection只创建⼀次,然⽽确牺牲了性能。改⽤

ConcurrentHash的情况下,⼏乎可以避免加锁的操作,性能⼤⼤提⾼,但是在⾼并发的情况下有可能出现

Connection被创建多次的现象。

这时最需要解决的问题就是当key不存在时,创建Connection的动作能放在connectionPool之后执⾏,这正是FutureTask发挥作⽤的时

机,基于ConcurrentHashMap和FutureTask的改造代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

privateConcurrentHashMap>connectionPool=newConcurrentHashMap

FutureTask>();

publicConnectiongetConnection(Stringkey)throwsException{

FutureTaskconnectionTask=(key);

if(connectionTask!=null){

();

}

el{

Callablecallable=newCallable(){

@Override

publicConnectioncall()throwsException{

//TODOAuto-generatedmethodstub

returncreateConnection();

}

};

FutureTasknewTask=newFutureTask(callable);

connectionTask=bnt(key,newTask);

if(connectionTask==null){

connectionTask=newTask;

();

}

();

}

}

//创建Connection(根据业务需求,⾃定义Connection)

privateConnectioncreateConnection(){

returnnull;

}

经过这样的改造,可以避免由于并发带来的多次创建连接及锁的出现。

3部分源码分析

3.1构造⽅法

1

2

3

4

publicFutureTask(Runnablerunnable,Vresult){

le=le(runnable,result);

=NEW;//ensurevisibilityofcallable

}

3.2cancel

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

//这个⽅法有⼀个参数是否中断running

publicbooleancancel(booleanmayInterruptIfRunning){

/**

*这个有点晕啊逻辑关系是

*等价与if(state!=new||!eAndSwapInt(this,stateOfft,NEW,mayInterruptIfRunning?INTERRUPTING:

CANCELLED))

*这个意思是如果state不是new那么就退出⽅法,这时的任务任务坑是已经完成了或是被取消了或是被中断了

*如果是state是new就设置state为中断状态或是取消状态

*

**/

if(!(state==NEW&&

eAndSwapInt(this,stateOfft,NEW,

mayInterruptIfRunning?INTERRUPTING:CANCELLED)))

returnfal;

try{//incacalltointerruptthrowxception

//如果是可中断那么就调⽤系统中断⽅法然后把状态设置成INTERRUPTED

if(mayInterruptIfRunning){

try{

Threadt=runner;

if(t!=null)

upt();

}finally{//finalstate

eredInt(this,stateOfft,INTERRUPTED);

}

}

}finally{

finishCompletion();

}

returntrue;

}

以上为个⼈经验,希望能给⼤家⼀个参考

本文发布于:2022-11-15 20:13:20,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/88/26452.html

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

上一篇:eqs是什么意思
标签:furture
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图