一、来由
请看看下述示例,猜猜输出结果:
public class ThreadPoolExample {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(1),
new ThreadFactoryBuilder().setNameFormat("task-[%d]").build(), new DiscardPolicy());
List<Callable<String>> futureTasks = new ArrayList<>();
for (int i = 0; i < 5; i++) {
futureTasks.add(new MyTask(i));
}
try {
List<Future<String>> futures = executor.invokeAll(futureTasks);
for (Future<String> future : futures) {
System.out.println("future.get : " + future.get());
}
} catch (InterruptedException e) {
System.out.println(e);
} catch (Exception e) {
System.out.println(e);
}
}
static class MyTask implements Callable<String> {
private int index;
public MyTask(int index) {
this.index = index;
}
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + ": task execute " + index);
return "task " + index;
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(Thread.currentThread().getName() + ": reject task ");
}
}
public static class ThreadFactoryBuilder {
private String nameFormat = null;
public ThreadFactoryBuilder setNameFormat(String nameFormat) {
String.format(nameFormat, 0); // fail fast if the format is bad or null
this.nameFormat = nameFormat;
return this;
}
public ThreadFactory build() {
return build(this);
}
private static ThreadFactory build(ThreadFactoryBuilder builder) {
final String nameFormat = builder.nameFormat;
final ThreadFactory backingThreadFactory = Executors.defaultThreadFactory();
final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;
return runnable -> {
Thread thread = backingThreadFactory.newThread(runnable);
if (nameFormat != null) {
thread.setName(String.format(nameFormat, count.getAndIncrement()));
}
thread.setDaemon(false);
return thread;
};
}
}
}
猜猜看上面的程序将输出什么?
如果将拒绝策略改为ThreadPoolExecutor.CallerRunsPolicy
呢?
- 使用直接丢弃策略的输出值为:
task-[0]: task execute 0
task-[0]: task execute 1
main: reject task
main: reject task
task-[0]: task execute 3
- 使用
ThreadPoolExecutor.CallerRunsPolicy
拒绝策略的输出值为:
main: task execute 2
task-[0]: task execute 0
task-[0]: task execute 1
main: task execute 4
task-[0]: task execute 3
future.get : task 0
future.get : task 1
future.get : task 2
future.get : task 3
future.get : task 4
分析上述两个结果发现,当直接把FutureTask
任务丢弃后,future.get
便不再输出,仅仅拒绝策略的不同,结果却大相径庭,这是为何呢?
让我们接着往下看
二、线程池简介
首先,让我们来看看ThreadPoolExecutor
所为何物。
这是ThreadPoolExecutor
的构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:线程存活时间
- unit:线程存活时间的单位
- workQueue:工作队列