线程池构造参数
int corePoolSize, 核心线程数 小于corePoolSize创建新新线程 等于corePoolSize任务保存到队列 prestartAllCoreThreads() 一次性启动所有核心线程
int maximumPoolSize, 最大线程数 队列满了,小于maximumPoolSize创建新新线程
long keepAliveTime, 线程空闲下来后,存活的时间,只在大于corePoolSize才有用
TimeUnit unit, 存活时间单位值
BlockingQueue<Runnable> workQueue, 保存任务的队列
ThreadFactory threadFactory, 创建线程的工厂,给新建的线程赋予名字
RejectedExecutionHandler handler 饱和策略
AbortPolicy: 直接抛出异常 默认
CallerRunsPolicy:用调用者所在的线程来执行任务
DiscardOldestPolicy: 丢弃阻塞队列里最老的任务,队列里最靠前的任务
DiscardPolicy: 当前任务直接丢弃
线程池提交方式
execute(Runnable command) 不需要返回
Future<T> submit(Callable<T> task) 需要返回
线程池数量
计算密集型:加密,大数据分解,正则..... 线程数适当小点 最大推荐:机器cpu核心数(Runtime.getRuntime().availableProcessors())+1 防止页缺失,
IO密集型:读取文件,数据库连接,网络通讯,线程数适当大一点,最大推荐:机器cpu核心数*2
常用线程池
ScheduledThreadPoolExecutor
scheduleAtFixedRate 任务1开始时间与任务2开始时间间隔相同,当任务1执行时间大于间隔时间,会在任务1执行完成后,立即执行任务2
scheduleWithFixedDelay 任务1结束时间与任务2开始时间间隔相同
线程池基本使用流程
类的线程安全定义
栈封闭 所有的变量都是在方法内部声明的,这些变量都处于栈封闭状态
无状态 没有任何成员变量的类,就叫无状态的类
让类不可变 加final关键字,对于一个类,所有的成员变量应该是私有的,同样的只要有可能,所有的成员变量应该都加上final关键字;根本不提供任何可供修改成员变量的地方
volatile 保证类的可见性
加锁和CAS
安全的发布
ThreadLocal
线程性能与思考
影响性能的因素:上下文切换,内存同步
减少锁的竞争:缩小锁的范围,减少锁的粒度,锁分段,替换独占锁