本文只会对原有jar包自带线程池进行讲述,讲解自己使用过程。
初步方案
开始接触时,项目中由于对接口调用时间要求比较高,QPS较高,机器较少,导致需要对于程序性能作高度的优化,所以使用线程池对独立逻辑进行多线程处理。
ExecutorService executor = Executors.newFixedThreadPool(n ==0?1: n);
实现Callable接口,构造FutureTask
if (!executor.isShutdown()) {
executor.submit(task);
}
然后取出FutureTask的对应结果,包括异常会随之抛出。
但是这不是关键问题,关键问题是:在每一个接口中都创建了线程池,即有请求进来时,会消耗很多的系统性能,导致线上机器的负载上升(实际处理时间还是很快,接口有缓存)。
优化方案
本地实现一个单例的线程池(线程池的大小需要慎重考虑)
public class ExecutorTask {
private ExecutorService executor = Executors.newFixedThreadPool(100000);
private static class SingleExecutorTask {
private static final ExecutorTask executorTask = new ExecutorTask();
}
private ExecutorTask() { }
public static ExecutorTask getInstance() {
return SingleExecutorTask.executorTask;
}
public <T> TaskFuture executeTask(final Task<T> t) {
Future<T> future = executor.submit(new Callable<T>() {
@Override
public T call() throws Exception {
return t.runTask();
}
});
return new TaskFuture(future);
}
}
public interface Task<T> {
T runTask();
}
public class TaskFuture<V> {
private Future<V> future;
public TaskFuture(Future<V> future) {
this.future = future;
}
public V getResp() throws Exception {
return future.get();
}
}
这样子只需要根据不同类型的任务,实现task接口,即可根据适用不同的任务,同时可以减少很多的重复代码。
网友评论