ExecutorService es = new ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
常用线程池
- corePoolSize(必填): 核心线程数
- maximumPoolSize(必填): 最大线程数
- keepAliveTime(必填): 非核心线程存活时间(超过存活时间被收回,核心线程不会被回收;非核心线程 = 最大线程数 - 核心线程数)
- unit(必填): 存活时间单位,用TimeUnit里的常量来设置单位
- workQueue(必填): 阻塞队列
- threadFactory(选填): 创建线程的工厂
- handler(选填): 拒绝策略;默认是抛出异常
executor和submit的区别常用线程池指的就是Executors中的那些静态方法;底层实现都是用的ThreadPoolExecutor来new出来的,这些常用的区别就是其中的参数不同,
- 定时: newScheduledThreadPool; 阻塞队列用的是: DelayedWorkQueue
- 定长: newFixedThreadPool; 阻塞队列用的是: linkedBlockingQueue(无界阻塞队列)
- 可缓存: newCachedThreadPool; 阻塞队列用的是: SynchronousQueue(入队(put)和出队(take)必须同时执行)
- 单线程: newSingleThreadExecutor; 阻塞队列用的是: linkedBlockingQueue
线程池执行过程
- executor只接收Runnable类型参数;submit可以接收Callable,也可以接收Runable,有返回值;
- executor没有返回值; submit有返回值;
- executor会抛异常; submit不会抛异常(只有线程池对象调用submit方法;该方法的返回值调用get方法才会抛出异常)
首先new出一个线程池之后;在这个线程池中没有线程,只有在执行executor方法的时候才会去创建线程;所以具体实现都在executor这个方法里,下面详细解读这个executor方法;
第一步: 判断线程池中已存在的线程数是否小于核心线程数;小于的话就去创建线程然后执行任务;不小于进入第二步
第二步: 判断阻塞队列满没满;没满,就进入阻塞队列,等待线程执行;满了,就进入第三步
第三步: 判断已存在的线程数是否小于最大线程数;小于的话就去创建线程执行当前进来的任务;不小于的话就执行拒绝策略
注:
- 在第一步中,只要当前线程总数小于核心线程数,都会创建一个新的线程(如果这个时候当前线程都是空闲状态,还是会创建新的线程)
- 核心线程是不会被回收的;创建线程池传入的线程存活时间是针对于非核心线程的;如果非要想让核心线程也按照这个存活时间来回收,可以在创建完线程池之后,紧接着执行: 线程池对象.allowCoreThreadTimeOut(true);



