Java线程池 / Executor / Callable / Future
为什么需要线程池?
每次都要new一个thread,开销大,性能差;不能统一管理;功能少(没有定时执行、中断等)。
使用线程池的好处是,可重用,可管理。
Executor
4种线程池
// 可缓存线程池,如果缓存中没有可用的,则移出60秒未使用过的线程
ExecutorService service= Executors.newCachedThreadPool();
// 大小固定的线程池
ExecutorService service= Executors.newFixedThreadPool(5);
// 单线程,是线程量=1的FixedThreadPool,多任务下相当于排队。
ExecutorService service= Executors.newSingleThreadPool();
// 支持定时和周期,一般情况下可替代timer
ScheduledExecutorService exec = Executors.newScheduledThreadPool(int corePoolSize)
Demo
ExecutorService pool= Executors.newCachedThredPool();
pool.ececute(new Runable());
// 关闭,不再接受新的任务请求
pool.shutdown();
// 立即关闭,停止接受task,
pool.showdownNow();
Future
.submit(Runnable) 返回一个Future,主要目的是检查任务执行的状况(是否完成,有无异常)。
interface Future<V>
{
V get() throws ...;
V get(long timeout,TimeUnit unit) throws ..;
void cancel(boolean mayInterrupt); // 取消任务,如果已经开始,mayInterrupt=true时被中断
boolean isCancelled();
boolean isDown();
}
Future task = pool.submit(new Runnable());
task.isDone(); //
task.get(); // 阻塞当前线程,如果task在执行过程中有异常,则会在这里重新抛出
Callable
Runnable没有返回值,Callable<E>有返回值;
submit一个runnable,不能知道运行结果,可以submit一个callable。
// 创建callable
class MyCallable implements Callable<Integer>
{
@Override
public Integer call()
{
return 1;
}
}
Future<Integer> task = pool.submit(new MyCallable());
task.get(); // 阻塞,显示结果
FutureTask
同时包装了Future和Task。
Callable<Integer> c = ...;
FutureTask<Integer> t = new FutureTask<Integer>(c);
new Thread(task).start();
Integer r = t.get();
CompletionService
completionService = new ExecutorCompletionService<Long>(exec);
for(){
completionService.submit(new Callable());
}
// 取完成的任务,如果没有,就阻塞等待
completionService.take().get()