码迷,mamicode.com
首页 > 编程语言 > 详细

线程池(二)

时间:2019-09-17 19:21:08      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:Fix   操作   设计思想   submit   done   并发编程   executors   管理   get   

Future

在并发编程中,我们经常用到非阻塞的模型,在之前的多线程的三种实现中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。
Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。

接口和类:

Future接口定义了主要的5个接口方法,有RunnableFuture和SchedualFuture继承这个接口,以及CompleteFuture和ForkJoinTask。

RunnableFuture(接口)

这个接口同时继承Future接口和Runnable接口,在成功执行run()方法后,可以通过Future访问执行结果。

FutureTask (实现类)

FutureTask 提供了Future的基本实现,可以实现了启动和取消一个方法,查询这个方法是否已完成。一旦计算完成,这个计算将不能被重启和取消,除非调用runAndReset方法。
  FutureTask能用来包装一个Callable或Runnable对象,因为它实现了Runnable接口,而且它能被传递到Executor进行执行。为了提供单例类,这个类在创建自定义的工作类时提供了protected构造函数。
  通过CAS操作保证状态的变更,通过自旋锁+线程挂起+唤醒的方式来实现阻塞实现类:FutureTask

Future的主要方法

get()方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完毕
get(long timeout,TimeUnit unit)做多等待timeout的时间就会返回结果
cancel(boolean mayInterruptIfRunning)方法可以用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false.
isDone()方法判断当前方法是否完成
isCancel()方法判断当前方法是否取消

PS

FutureTask 可以直接当做Runnable实现类传给 Thread 执行或者 放在executorService 的submit 中,FutureTask 中的 run() 方法,会判断类型是不是call()方法。AbstractExecutorService 中有submit(call) 方法,

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
}

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

Java提供的线程池

FixedThreadPool 

容量固定的线程池。活动状态和线程池容量是有上限的线程池。所有的线程池中,都有一个任务队列。只有核心线程,且数量固定,没有非核心线程。使用的是BlockingQueue<Runnable>作为任务的载体。当线程有空闲的,自动从队列中取出任务执行。

使用场景: 大多数情况下,使用的线程池,首选推荐FixedThreadPool。OS系统和硬件是有线程支持上限。不能随意的无限制提供线程池。

队列默认的容量上限是Integer.MAX_VALUE,基本就是无界队列。

常见的线程池容量: PC - 200。 服务器 - 1000~10000

CachedThreadPool

缓存的线程池。容量不限(Integer.MAX_VALUE)。自动扩容。容量管理策略:如果线程池中的线程数量不满足任务执行,创建新的线程。默认线程空闲60秒,自动销毁。

应用场景: 内部应用或测试应用。 如:电信平台夜间执行数据整理(有把握在短时间内处理完所有工作,且对硬件和软件有足够的信心)。 测试应用,在测试的时候,尝试得到硬件或软件的最高负载量,用于提供FixedThreadPool容量的指导。

SingleThreadExceutor 

单一容量的线程池。

使用场景: 保证任务顺序时使用。如: 游戏大厅中的公共频道聊天。秒杀。

ForkJoinPool

分支合并线程池(mapduce类似的设计思想)。适合用于处理复杂任务。初始化线程容量与CPU核心数相关。

线程池中运行的内容必须是ForkJoinTask的子类型(RecursiveTask,RecursiveAction)。RecursiveTask有返回结果的分支合并任务,RecursiveAction无返回结果的分支合并任务。(Callable/Runnable)compute方法:就是任务的执行逻辑。

ForkJoinPool没有所谓的容量。默认都是1个线程。根据任务自动的分支新的子线程。当子线程任务结束后,自动合并。所谓自动是根据fork和join两个方法实现的。

应用: 主要是做科学计算或天文计算的。数据分析的。

技术图片

 

线程池(二)

标签:Fix   操作   设计思想   submit   done   并发编程   executors   管理   get   

原文地址:https://www.cnblogs.com/RobertLionLin/p/11536011.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!