FutureTask是对Future的基本实现,具有启动和取消计算的方法,查询计算是否完整,并检索计算结果。FutureTask对Future做了一定得扩展:
void run() //将此future设置为其计算结果,除非已被取消。
protected boolean runAndReset() //执行计算而不设置其结果,然后重置为初始状态,如果计算遇到异常或被取消,则不执行此操作。
protected void set(V v) //将此Future的结果设置为给定值,除非Future已被设置或已被取消。
protected void setException(Throwable t) //除非已经设置了此 Future 或已将其取消,否则它将报告一个 ExecutionException,并将给定的 throwable 作为其原因。
FutureTask除了实现Future接口外,还实现了Runnable接口。所以FutureTask可以由Executor执行,也可以由调用线程直接执行futureTask.run()。
当FutureTask处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞;
当FutureTask处于已完成状态时,执行FutureTask.get()方法将导致调用线程立即返回结果或抛出异常。
当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将导致此任务永远不会被执行;
当FutureTask处于已启动状态时,执行FutureTask.cancel(true)方法将以中断执行此任务线程的方式来尝试停止该任务;
当FutureTask处于已启动状态时,执行FutureTask.cancel(false)方法将不会对正在执行此任务的线程产生影响(让正在执行的任务运行完成)。
关于是否使用Executors
在之前阿里巴巴出的java开发手册中,有明确提出禁止使用Executors:
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,
这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
在上面我们分析过使用Executors创建的几种线程池的使用场景和缺点,大多数情况下出问题在于可能导致OOM,在我实际使用中基本没有遇到过这样的情况。但是考虑到阿里巴巴这样体量的并发请求,可能遇到这种情况的几率较大。所以我们还是应该根据实际情况考虑是否使用,当然实际遵循阿里巴巴开发手册来可能会更好一点,毕竟这是国类顶尖公司常年在生产中积累下的经验。
最后,在本节中只是简单介绍线程池及其基本原理,帮助更好的理解线程池。并不涉及具体如何使用。
Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx