话不多说,直接上代码,要说的都在代码注释里面:
public class ThreadPools {
//TODO:ThreadPoolExecutor的执行规则——
//1.如果线程池中的线程数量未达到核心线程的数量,那么直接启动一个核心线程;
//2.如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等待执行。
//3.如果在步骤2中无法将任务插入到任务队列中,这往往是因为任务队列已满,这时如果线程池先吃数量未达到线程池规定的最大值,会立即启动一个非核心线程来执行任务。
//4.如果步骤3中的线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。
public static void main(String[] args) {
ExecutorService service = getCachedThreadPool(new Runnable() {
@Override
public void run() {
System.out.println("风满楼,卷黄沙,舞剑春秋,名震天下;雨缥缈,眷红尘,还君明珠,秋水浮萍,");
}
});
//一定要在合适的地方调用shutdown()方法,以避免内存泄漏。
//TODO:shutdown()关闭线程,调用这个方法的时候,线程不一定会立即关闭,因为可能任务还没有执行完毕。
//TODO:shutdownNow()关闭线程,调用这个方法的时候,直接关闭,不管还有没有任务执行。
//TODO:isShutdown(),只要调用了shutdown()方法,就会返回true;
//TODO:isTerminated(),任务执行完成的后,isTerminated()方法才会返回true;
//TODO:所以采用一个while死循环+判断isTerminated()的方法来确定任务是否执行完成。
service.shutdown();
System.out.println(service.isShutdown());
System.out.println(service.isTerminated());
}
/**
* 创建一个根据需要创建新线程的线程池,它没有核心线程,对线程池大小没有做限制,理论上可以有无线多个,实际上线程池大小完全依赖于JVM
* 如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,
* 当任务数增加时,此线程池又可以智能的添加新线程来处理任务。
* @param runnable
*/
public static ExecutorService getCachedThreadPool(Runnable runnable){
ExecutorService service = Executors.newCachedThreadPool();
service.execute(runnable);
return service;
}
/**
* 创建一个单线程的线程池
* @param runnable
*/
public static ExecutorService getSingleThreadPool(Runnable runnable){
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(runnable);
return service;
}
static ExecutorService newFixedThreadPoolService = null;
/**
* 创建一个可重用的固定长度的线程池,控制线程最大并发数,超出的线程会在队列中等待。
* @param nThreads:线程池长度
* @param runnable:线程
*/
public synchronized static ExecutorService getNewFixedThreadPool(int nThreads, Runnable runnable){
if (null == newFixedThreadPoolService){
newFixedThreadPoolService = Executors.newFixedThreadPool(nThreads);
}
newFixedThreadPoolService.submit(runnable);
return newFixedThreadPoolService;
}
static ExecutorService newScheduledThreadPoolService = null;
/**
* 创建一个定长线程池,支持定时及周期性任务执行。
* @param nThreads:线程池可缓存线程的数量
* @param runnable:线程
*/
public synchronized static ExecutorService getScheduledThreadPool(int nThreads, Runnable runnable){
if (newScheduledThreadPoolService == null){
newScheduledThreadPoolService = Executors.newScheduledThreadPool(nThreads);
}
newScheduledThreadPoolService.submit(runnable);
return newScheduledThreadPoolService;
}
static ScheduledExecutorService mScheduledExecutorServiceFixedRate;
/**同getScheduledThreadPoolExecutor()方法*/
public synchronized static ScheduledExecutorService getScheduledExecutorServiceFixedRate(
int nThreads, Runnable runnable, long initialDelay, long period, TimeUnit unit){
if (mScheduledExecutorServiceFixedRate == null){
mScheduledExecutorServiceFixedRate = Executors.newScheduledThreadPool(nThreads);
}
mScheduledExecutorServiceFixedRate.scheduleAtFixedRate(runnable, initialDelay, period, unit);
return mScheduledExecutorServiceFixedRate;
}
static ScheduledExecutorService mScheduledExecutorServiceFixedDelay;
/**同getScheduledThreadPoolExecutorWithFixedDelay()方法*/
public synchronized static ScheduledExecutorService getScheduledExecutorServiceFixedDelay(
int nThreads, Runnable runnable, long initialDelay, long period, TimeUnit unit){
if (mScheduledExecutorServiceFixedDelay == null){
mScheduledExecutorServiceFixedDelay = Executors.newScheduledThreadPool(nThreads);
}
mScheduledExecutorServiceFixedDelay.scheduleWithFixedDelay(runnable, initialDelay, period, unit);
return mScheduledExecutorServiceFixedDelay;
}
//TODO:ScheduledThreadPoolExecutor创建线程池。它使用的工作队列是DelayedWorkQueue,DelayedWorkQueue是一个无界队列;我们仅仅需要指定其核心线程数量
static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = null;
/**
* 创建一个可缓存并且可以周期性执行任务的线程池,优先保证任务执行的频率。
* 该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。
* 如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。
* @param nThreads:线程池可缓存线程的数量
* @param runnable:线程
* @param initialDelay:延迟执行的时间
* @param period:每次任务执行的时间间隔
* @param unit:时间单位——S,ms,min,h......
*/
public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor(
int nThreads, Runnable runnable, long initialDelay, long period,TimeUnit unit){
if (null == scheduledThreadPoolExecutor){
scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(nThreads);
}
// scheduleAtFixedRate:该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。
// 注意,period是从任务开始执行算起的。开始执行任务后,定时器每隔period时长检查该任务是否完成,
// 如果完成则再次启动任务,否则等该任务结束后才再次启动任务。
scheduledThreadPoolExecutor.scheduleAtFixedRate(runnable, initialDelay, period, unit);
return scheduledThreadPoolExecutor;
}
static ScheduledThreadPoolExecutor scheduleWithFixedDelay;
/**
* 创建一个可缓存并且可以周期性执行任务的线程池,优先保证任务执行的间隔。
* 任务在在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
* 如果任务执行过程中抛出了异常,那么过ScheduledExecutorService就会停止执行任务,且也不会再周期地执行该任务了。
* 所以你如果想保住任务都一直被周期执行,那么catch一切可能的异常。
* @param nThreads:线程池可缓存线程的数量
* @param runnable:线程
* @param initialDelay:延迟执行的时间
* @param period:每次任务执行的时间间隔
* @param unit:时间单位——S,ms,min,h......
*/
public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutorWithFixedDelay(
int nThreads, Runnable runnable, long initialDelay, long period, TimeUnit unit){
if (null == scheduleWithFixedDelay){
scheduleWithFixedDelay = new ScheduledThreadPoolExecutor(nThreads);
}
// 在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
scheduleWithFixedDelay.scheduleWithFixedDelay(runnable, initialDelay, period, unit);
return scheduleWithFixedDelay;
}
static ScheduledThreadPoolExecutor scheduleService = null;
/**
* 创建一个可缓存并且可以周期性执行任务的线程池,任务在延迟delay时长后执行,只执行一次。
* @param nThreads:线程池可缓存线程的数量
* @param runnable:线程
* @param delay:延迟执行的时间
* @param unit:时间单位——S,ms,min,h......
*/
public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor(
int nThreads, Runnable runnable, long delay, TimeUnit unit){
if (null == scheduleService){
scheduleService = new ScheduledThreadPoolExecutor(nThreads);
}
// schedule方法调度的任务在delay时长的延迟后只执行一次。
scheduleService.schedule(runnable, delay, unit);
return scheduleService;
}
static ScheduledThreadPoolExecutor scheduleServiceExecute = null;
/**
* 创建一个可缓存的线程池
* @param nThreads:线程池可缓存线程的数量
* @param runnable:线程
*/
public synchronized static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutorExecute(int nThreads, Runnable runnable){
if (null == scheduleServiceExecute){
scheduleServiceExecute = new ScheduledThreadPoolExecutor(nThreads);
}
// execute方法调度的任务异步执行。
scheduleServiceExecute.execute(runnable);
return scheduleServiceExecute;
}
}
执行结果: