扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
这篇文章主要介绍了Callable与Runnable有什么区别,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
创新互联公司是专业的佛山网站建设公司,佛山接单;提供网站设计、网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行佛山网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
java.lang.Runnable是一个接口,只有一个run()方法
public interface Runnable { public abstract void run(); }
run()方法
的返回值是void,故在执行完任务后无法返回任何结果
Callable是java.util.concurrent包下的,也是一个接口,也只有一个call()方法
,类似于java.lang.Runnable的run()方法
,实现Callable接口的类和实现Runnable接口的类都是可以被其它线程执行的任务
public interface Callable{ V call() throws Exception; }
可以看到call()方法是有返回值的,可以将执行的结果返回
Callable和Runnable的区别:
1、Callable中定义的是call()方法,Runnable中定义的是run()方法
2、Callable中的call()方法可以返回执行任务后的结果,Runnable中的run()方法无法获得返回值
3、Callable中的call()方法定义了throws Exception抛出异常,抛出的异常可以在主线程Future.get()时被主线程捕获;Runnable中的run()方法没有定义抛出异常,运行任务时发生异常时也会上抛,因为即使不加默认也会上抛RuntimeException,但异常无法被主线程获取
4、运行Callable任务可以拿到一个Future对象代表异步运算的结果
1、有了Runnable,为什么还需要Callable,它们的区别是什么?
Runnable和Callable都表示执行的任务,但不同的是Runnable.run()方法没有返回值,Callable.call()有返回值
但其实线程在执行任务时还是执行的Runnable.run()方法,所以在使用ThreadPoolExecutor.submit()时会将Callable封装为FutureTask,而FutureTask是Runnable和Future的实现类,所以在执行Callable的任务时,线程其实是执行FutureTask这个Runnable的run()方法,其中封装了调用Callable.call()并返回结果的逻辑。执行Runnable任务如果发生异常,主线程无法知晓;而执行Callable任务如果发生异常,在Future.get()时会抛出java.util.concurrent.ExecutionException,其中封装了真实异常
2、Future.get()是如何获取线程返回值的?
首先得益于Callable.call()方法定义了返回值,提交Callable任务后,Callable会被封装成FutureTask,其既可以作为Runnable被执行,也可以作为Future获取返回值,FutureTask.run()方法会调用Callable.call()中的任务代码。在任务执行完成前,如果主线程使用Future.get(),其实是调用FutureTask.get(),其中会判断任务状态尚未结束,将主线程加入waiters等待链表,并挂起主线程。待任务执行结束后,FutureTask会唤醒所有等待获取返回值的线程,此时主线程的FutureTask.get()就会返回了。所以,主线程和运行线程是通过FutureTask作为桥梁获取线程返回值的。
3、Future.cancel()真的能取消任务的执行吗?
首先答案是“不一定”,根据JDK中的方法注释“Attempts to cancel execution of this task”,即尝试去取消执行的任务。如果任务正在执行,且调用cancel()时,参数mayInterruptIfRunning传的是true,那么会对执行线程调用interrupt()方法。那么问题就变成了interrupt()方法能中断线程执行吗?interrupt()方法不会中断正在运行的线程。这一方法实际上完成的是在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait()、Thread.join()、Thread.sleep()等阻塞,那么它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
如果线程没有被阻塞,调用interrupt()将不起作用,那么即使线程正在阻塞状态,并抛出了InterruptedException,线程能否真的取消执行还要看代码中是否捕获了InterruptedException和有没有做相应的对中断标示的判断逻辑。
感谢你能够认真阅读完这篇文章,希望小编分享的“Callable与Runnable有什么区别”这篇文章对大家有帮助,同时也希望大家多多支持创新互联,关注创新互联行业资讯频道,更多相关知识等着你来学习!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流