1 线程实现
进程 拥有独立的内存空间
线程 内核态线程,操作系统调度的最小单位,包含在进程之中,是进程中的实际运作单位
协程 用户态线程,POSIX 早期的线程实现,由 runtime 自行调度
1.1 状态机
NEW 线程已创建,但尚未启动。
RUNNABLE 在OS层面,ready 获得CPU时间分片后进入到running
BLOCKED 阻塞,等待 monitor lock。
WAITING 永久等待,直至其它线程通知。
TIMED_WAITING 限时等待,直至其它线程通知、超时。
TERMINATED 线程已执行完run() 或 执行过程中抛出异常。
1.2 守护线程
任一线程退出时,JVM会检测运行中的线程,如果都是守护线程,那么JVM直接退出。
JVM 启动时创建的线程中,main 是非守护线程,Finalizer、Signal Dispatcher、Reference Handler 都是守护线程。
2 上下文切换
2.1 原理
2.2 成本监控
3 线程池
Java 使用 LWP 实现线程,上下文切换开销大,并且占用内存 1MB,到了 JDK11 才优化为 40KB。因为线程很昂贵,所以要池化线程资源,提供复用。
3.1 状态机
3.2 ThreadPoolExecutor
- poolSize < corePoolSize,创建线程来执行任务(执行时需要获取全局锁)
- poolSize >= corePoolSize,把 task 压入 workQueue
- workQueue 已满,创建临时线程
- poolSize > maximumPoolSize,执行拒绝策略
AbortPolicy 丢弃任务,抛出异常,默认策略
DiscardPolicy 丢弃任务,不抛异常
DiscardOldestPolicy 丢弃 workQueue 中靠最老的任务,并执行当前任务
CallerRunsPolicy 用调用者的线程来执行任务,所以 execute、submit 有可能阻塞3.3 调优参数
taskCount 线程需要执行的任务个数
getActiveCount 活动的线程的数量
getPoolSize 当前线程池的线程数量
largestPoolSize 曾经创建过的最大线程数量
继承线程池,重写 beforeExecute、afterExecute、terminated,在线程执行任务前,线程执行任务结束,和线程终结前获取线程的运行情况,根据具体情况调整线程池的线程数量。3.4 Executors
scheduled DelayedWorkQueue
cached SynchronousQueue
fixed LinkedBlockingQueue
single 同 fixed参考文献