比较java中Future与FutureTask之间的关系

2025-05-29 0 48

futurefuturetask都是用于获取线程执行的返回结果。下面我们就对两者之间的关系与使用进行一个大致的介绍与分析

一、futurefuturetask介绍:

future位于java.util.concurrent包下,它是一个接口

?

1

2

3

4

5

6

7

8
public interface future<v> {

boolean cancel(boolean mayinterruptifrunning);

boolean iscancelled();

boolean isdone();

v get() throws interruptedexception, executionexception;

v get(long timeout, timeunit unit)

throws interruptedexception, executionexception, timeoutexception;

}

future接口中声明了5个方法,下面介绍一下每个方法的作用:

cancel方法用来取消任务,取消成功则返回true,取消失败则返回false。参数mayinterruptifrunning设置为false,表示不允许在线程运行时中断,设置为true则表示允许。具体可分为以下三种情况:

1、如果任务已经完成,则无论mayinterruptifrunning为true还是false,都返回false,这是因为你要取消的任务已经完成,则认为取消任务失败;

2、如果任务正在执行,则无论mayinterruptifrunning为true还是false,都返回true。只不过mayinterruptifrunning为true时线程会被中断,false时线程不会被中断会执行完。

3、如果任务还没有执行,则无论mayinterruptifrunning为true还是false,都返回true。

iscancelled方法用于判断任务是否被取消成功,cancel方法成功则返回 true,反之则为false。

isdone用于判断任务是否完成, 如果任务完成则返回true。任务完成包括正常结束、任务被取消、任务发生异常,都返回true

get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;

get(long timeout, timeunit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,抛出 java.util.concurrent.timeoutexception 异常

futuretask 实现了runnablefuture接口,而runnablefuture则继承了future<v>与runnable接口,所以 futuretask不仅实现了 future<v>接口的所有方法,还具有自己的run方法,我们可以看下它的类图

比较java中Future与FutureTask之间的关系

二、futurefuturetask使用与分析

1、使用future时,我们需要实现callable接口,并通过executorservice接口的submit方法获取返回的future对象,

2、使用futuretask时,根据futuretask的构造函数可以看到futuretask既可以接收callable的实现类,也可以接收runnable的实现类。当你传入的是callable的实现类时,可以获取线程执行的结果;传入runnable的实现类时,由于runnable的实现没有返回值,需要传入一个你设置的线程完成标识,也就是result,然后当线程结束时会把你传入的result原值返回给你,futuretask的构造函数具体如下:

?

1

2

3

4

5

6

7

8

9

10

11

12
public class futuretask<v> implements runnablefuture<v>{

public futuretask(callable<v> callable) {

if (callable == null)

throw new nullpointerexception();

this.callable = callable;

this.state = new; // ensure visibility of callable

}

public futuretask(runnable runnable, v result) {

this.callable = executors.callable(runnable, result);//runnable转化为callable

this.state = new; // ensure visibility of callable

}

接下来我们看下futurefuturetask具体的使用代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20
// 执行任务 实现runnable

futuretaskjobrunnable taskrun = new futuretaskjobrunnable();

// 执行任务 实现callable

futuretaskjobcallable taskcall = new futuretaskjobcallable();

string val = "ok";

// 线程运行成功后把,返回你传入的val值

futuretask<string> futuretaskrun = new futuretask<string>(taskrun, val);

// 线程运行,返回线程执行的结果

futuretask<string> futuretaskcall = new futuretask<string>(taskcall);

//声明线程池

executorservice executor = executors.newcachedthreadpool();

//future

future<string> future = executor.submit(taskcall);

system.out.println(future.get());

//futuretask

executor.submit(futuretaskcall);

system.out.println(futuretaskcall.get());

//futuretask自定义线程执行

new thread(futuretaskrun).start();

system.out.println(futuretaskrun.get());

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19
public class futuretaskjobcallable implements callable<string>{

public string call() throws exception {

system.out.println("futuretaskjobcallable已经执行了哦");

thread.sleep(1000);

return "返回结果";

}

}

public class futuretaskjobrunnable implements runnable {

public void run() {

try {

thread.sleep(1000);

} catch (interruptedexception e) {

// todo auto-generated catch block

e.printstacktrace();

}

system.out.println("futuretaskjobrunnable已经执行了哦");

}

}

根据上面的代码我们从executorservice接口中submit方法入手,看下abstractexecutorservice类对submit方法的具体实现。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24
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(runnable task, t result) {

if (task == null) throw new nullpointerexception();

runnablefuture<t> ftask = newtaskfor(task, result);

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;

}

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);

}

可以看到当你使用submit方法提交任务时,都会通过newtaskfor方法转换成futuretask对象,所以我们具体分析下上面代码中的三种情况:

1、如果你传入的是自己实现的runaable类或者callable类,那么sumbit方法自然会帮你自动封装为futuretask对象,运行后通过future对象获取结果。

2、你传入的已经是个自己构造的futuretask对象,由于futuretask其实是实现了runnable接口的,它本身就是个runaable实现类, sumbit方法还是会将它视为runnable类来进行封装,并最终会执行futuretask自己的run方法,一系列实现都在你传入的futuretask对象内完成,所以你可以直接通过自己构建的futuretask获取结果;

3、自己单独声明线程运行,跟第2点类似,futuretask本身就是个runnabel实现类,自然可以做为参数传入thread运行;

那么我们把自定义的runnable、callable实现类做为参数构造futuretask后,futturetask是如何运行的呢,我们可以看下futturetask中具体的代码实现

?

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
//你传入的runnable与callable实现类都会在构造函数中转化为callable

private callable<v> callable;

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();//运行后返回结果

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);

}

}

可以看到futuretask类本身的run方法,就是执行runnable、callable的实现类并获取返回结果的过程。

所以executorservice接口中submit方法归根结底还是要把你传入的对象封装成futuretask对象,并通过futuretask类的内部实现来获取结果的,返回的future接口对象也要依赖于futuretask实例化的,所以无论是直接传入自己的runnable、callable实现类还是构建futuretask传入,本质上都是通过futuretask去实现,没有什么区别;

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 比较java中Future与FutureTask之间的关系 https://www.kuaiidc.com/111057.html

相关文章

发表评论
暂无评论