1. 线程是什么
简单的讲,就是应用程序中的子程序,是能做事情的更小单位。
qq是个应用程序,而文字聊天,视频就是子程序了。说的更不好懂点,qq开了一个进程,然后又创建了一群线程小弟,进程可以做线程所有的事情,但是线程不行。
具体的差异就是,进程负责加载上下文->做事情(占用cpu)->保存上下文,而线程只会做事情,也只需要做事情。这样的分工是很有必要的,用公司打比方,ceo是稀缺资源,要是每个员工都是ceo那类型的,想想就很可怕。
同样程序这样分也是一种必然,合理并节约资源。能力不足也是有好处的,天生我才必有用,不必妄自菲薄,自知的人,总能找到一个合适的位置,安天命的。
2. 线程池是什么
如果线程是普通员工,那么线程池就是人力资源部门了。它负责,招人(创建线程),裁员(回收线程),以及繁琐的小事---先给多少人(线程初始大小),不够再给(可扩容线程池),人力不够等待(队列等待),经费不够只能招多少(线程最大值)。
而作为公司的老总,管理者,你只需要去要人做事就行了,这样的酸爽肯定不能或缺,所以线程池的出现也是必然的,也为我们省去了管理细节的痛苦。
3. 创建线程池
1. corePoolSize 核心池大小,可初始化大小。
2. maximumPoolSize 最大线程数,只有当队列不够时,才可能到达该值。
3. keepAliveTime 线程空闲时间,若超过该时间,会尝试回收该线程。具体回收方式跟设置有关,默认大于corePoolSize 才会被回收,可通过设置allowCoreThreadTimeOut(true),则到时间就回收。
4. unit 空闲超时单位 TimeUnit.DAYS(天),TimeUnit.HOURS(小时),TimeUnit.MINUTES(分钟)TimeUnit.SECONDS(秒),TimeUnit.MILLISECONDS(毫秒),TimeUnit.MICROSECONDS(微妙),TimeUnit.NANOSECONDS(纳秒)
5. workQueue 等待队列/阻塞队列
6. threadFactory 线程工厂
7. handler 当队列不够用,任务拒绝策略---ThreadPoolExecutor.AbortPolicy(放弃当前任务,抛出RejectedExecutionException异常),ThreadPoolExecutor.DiscardPolicy(放弃当前任务),ThreadPoolExecutor.DiscardOldestPolicy(放弃队列中首位任务,添加当前任务到末尾),ThreadPoolExecutor.CallerRunsPolicy(由线程池处理,不可测)
4. 线程池核心方法
- execute(Runnable) 执行任务 不返回结果
- submit(Runnable) 执行任务 得到返回结果
- shutdown() 关闭线程池,等待所有任务执行完毕
- shutdownNow() 立即关闭线程池,强制终止所有线程
5. 线程池状态
- RUNNING(0) 运行状态 可接受新任务
- SHUTDOWN(1) 尝试停止状态 不接受新任务,处理已有任务
- STOP(2) 停止状态 不接受新任务,强制停止正在运行的线程
- TERMINATED(3) 回收状态 当SHUTDOWN,STOP处理完事情,线程池标记为该状态
6. 线程池工作流程
接受参数初始化线程池对象,等待任务,默认线程数为0。当有任务出现时,线程数慢慢增长到核心大小,若可用线程不够,将任务放入队列,若队列不够根据策略处理新进任务。
此时,若是有最大线程数设置,尝试创建新线程,若超过,创建失败;若未设置最大上线,可无限扩容那种,一直创建,直到内存溢出。
当任务数下降时,根据设置回收空闲线程。如此往复,直到shutdown(),或shutdownNow(),才回收资源,结束生命周期。