线程池
线程池的优点:
1、提高资源利用率
线程池可以重复利用已经创建了的线程
2、提高响应速度
因为当线程池中的线程没有超过线程池的最大上限时,有的线程处于等待分配任务状态,当任务到来时,无需创建线程就能被执行。
3、具有可管理性
线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。
4、有效控制最大并发线程数,提高系统资源利用率,同时也可以避免过多的资源竞争,避免阻塞
5、提供定时执行、定期执行,单线程、并发数控制等功能
线程池 :- ThreadPoolExecutor
corePoolSize:核心线程数量
maximumPollSize:线程最大线程数
workQueue:阻塞队列,存储等待执行的任务(重要:会对线程池运行过程产生重大影响)
当线程池中的线程数量小于corePoolSize的时候,直接创建新的线程来处理任务,即是线程池中有空闲的线程;如果线程池中的线程数量大于corePoolSize并且小于maximumPollSize,只有当workQueue阻塞的时候,才去创建新的线程去处理任务;如果设置的corePoolSize和maximumPollSize相同的时候,那么创建的线程池的大小是固定的,此时如果有新的任务提交,如果workQueue未阻塞,则把任务放到workQueue里面,等待空闲线程取出任务执行,如果运行的线程数量大于maximumPollSize并且workQueue已经阻塞,则会有拒绝策略来指定由谁来执行任务;
keepAliveTime:线程没有任务执行的时候最多保持多久时间终止;
unit:keepAliveTime的时间单位
threadFactory:线程工厂,用来创建线程
rejectHandler:当拒绝处理任务时候的策略
构造一个线程池:
线程池的几种状态:
状态1:runing=>能接受新提交的任务,并且也能处理阻塞队列里面的任务
状态2:shutdown=>属于关闭状态;当一个线程池属于关闭状态时候,不能执行新提交的任务,但是会继续执行阻塞队列里面的任务;如果阻塞队列为空,线程池中的工作线程为空【当running状态线程池指向shutdown()时候进入此状态】
状态3:stop=>不能接受新任务并且也不能处理阻塞队列里面的任务,线程池中的工作线程数量为0;【当running状态线程池指向shutdownNow()时候进入此状态】
状态4:tidying=>所有的任务一终止,工作线程数为0时候进入该状态
状态5:terminated=>tidying状态调用terminated()后进入该状态
执行方法:
方法1:execute() 提交任务交给线程池执行
方法2:submit() 提交任务,能够返回执行结果 execute+Future
方法3:shutdown() 关闭线程池,等地啊任务都执行完
方法4:shutdownNow() 关闭线程池,不等任务执行完
方法5:getTaskCount() 线程池已执行和未执行的任务总数
方法6:getCompleteTaskCount() 已完成的任务数量
方法7:getPoolSize() 线程池当前的线程数量
方法8:getActiveCount() 当前线程池中正在指向任务的线程数量
通过Executors封装的的常用的四个线程池:
CachedThreadPool
SingleThreadPool
总结:这两个线程池的主要问题:堆积的请求处理队列可能会耗费非常大的内存,甚至导致OOM
FixThreadPool
ScheduledThreadPool
总结:这两个线程主要问题-> 线程数的最大数是Integer.MAX_VALUE,可能会导致创建数量非常多的线程,甚至OOM
线程池的合理配置:
CPU密集型任务,就需要尽量压榨CPU,参考值可以设置为NCPU+1
IO密集型任务,参考值可以设置为2*NCPU
为了更加明确线程池的运行规则,避免资源耗尽的风险,通常通过ThreadPoolExecutor手动创建线程池
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-%d").build(); ExecutorService pool = new ThreadPoolExecutor(5, 200, 0L, TimeUnit.MICROSECONDS, new LinkedBlockingDeque<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); pool.execute(()-> { log.info(Thread.currentThread().getName()); }); pool.shutdown();