/**
1.如果运行的线程少于corePoolSize,则Executor始终首选添加新的线程,而不进行排队。 2.如果运行的线程等于或多于corePoolSize,则Executor始终首选将请求加入队列,而不添加新的线程。 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出maximumPoolSize,在这种情况下,任务将被拒绝(抛出RejectedExecutionException)。 排队有三种通用策略: 1.直接提交: 工作队列的默认选项是synchronousQueue,它将任务直接提交给线程而不保持它们。 在此,如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。 此策略可以避免在处理可能具有内部依赖性的请求集时出现锁。 直接提交通常要求无界 maximumPoolSize 以避免拒绝新提交的任务。 当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增加的可能性。
2.无界队列: 使用无界队列(不是指maxPoolSize,而是指任务等待队列,例如无限容量的 LinkedBlockingQueue )将导致在所有corePoolSize线程都忙时新任务在队列中等待。 这样,创建的线程就不会超过corePoolSize(因此,maximumPoolSize的值也就无效了)。 即:如果第5个参数是 synchronousQueue,则 maximumPoolSize 有效 如果第5个参数是 LinkedBlockingQueue,则maximumPoolSize 无效
3.有界队列:当使用有限的 maximumPoolSize 时,且使用有界队列(如ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控制。 队列大小和最大池大小可能需要相互折衷:使用大型队列和小型池可以最大限度的降低CPU使用率、操作系统资源和上下文切换开销,但是可能导致人工降低吞吐量。 如果任务频繁阻塞,则系统可能为超过您许可的更多线程安排时间,使用小型队列通常要求较大的池大小,CPU使用率较高,但是可能遇到不可接受的调度开销,这样可会降低吞吐量。
总结:给任务安排线程的优先级:先考虑corePoolSize线程够不够 > 再考虑是否可以入队列 > 再考虑是否可以增加线程 > 抛出异常
*/
public class ThreadPoolUtils {
public static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolUtils.class);
/** 执行异步任务的线程池,默认用cached thread pool */
public static ThreadPoolExecutor executorService;
/** 核心线程数 */
public final static int DEFAULT_CORE_POOL_SIZE = 30;
/** 最大线程数 */
public final static int DEFAULT_MAX_POOL_SIZE = 200;
/** second */
public final static Long DEFAULT_KEEP_ALIVE_TIME = 60L;
public final static int DEFAULT_TASK_QUEUE = 20000;
static {
int coreSize = DEFAULT_CORE_POOL_SIZE;
int maxSize = DEFAULT_MAX_POOL_SIZE;
Long aliveTime = DEFAULT_KEEP_ALIVE_TIME;
int queue = DEFAULT_TASK_QUEUE;
executorService = new ThreadPoolExecutor(coreSize, maxSize, aliveTime,
TimeUnit.SECONDS, new LinkedBlockingQueue<>(queue));
}
public static <T> Future<T> addTask(Callable<T> callable){
return executorService.submit(callable);
}
public static <T> T get(Future<T> future,long time){
try {
if(future == null){
return null;
}
return future.get(time, TimeUnit.MILLISECONDS);
} catch (Exception e) {
LOGGER.warn("ThreadPoolUtils error, e",e);
return null;
}
}
public static void main(String[] args){
}
}