Executor

874 阅读2分钟

线程的运行状态

我们每创建jvm的一个线程的时候,对应的在内核空间的线程表里面就会创建一个线程与jvm的线程绑定

协程 (纤程,用户级线程)

由系统线程来切换纤程,为了今经尽可能压榨cpu资源

线程池

ThreadPoolExecutor

如果并发的请求数量非常多,但每个线程执行的时间很短,这样就会频繁的创建和销毁线程,如此一来会大大降低系统的效率。可能出现服务器在为每个请求创建新线程和销毁线,甚至可能执行任务的时间还没有创建线程池的时间长

int corePoolSize                   核心线程数
int maxmunPoolSize                 最大线程数=非核心线程+核心线程数
int KeepAliveTime                  最大允许线程不干活的时间
TimeUnit unit                      时间单位
BlockingQueue<Runnable> workQueue  任务存放未来得及执行的任务 
ThreadFactory threadFactory        创建线程的工厂
RejectedExecutionHandler handler   拒绝策略

1.第一步通过execute方法把任务提交给线程池,此时线程池如果没有线程优先创建核心线程,并把任务放入核心线程
2.第二步当核心线程>=5,把任务往阻塞队列里面放
3.第三步把任务往非核心线程里面放,把非核心线程全部创建满
4.第四步如果最大线程数都满了走拒绝策略

源码解析

1.workerCountOf(c)            获取当前线程数量

2.ddWorker(command, true)     判断线程池状态,把任务添加给核心线程

   2.1.new Worker(firstTask)  创建一个工人,并把任务给到他
   2.2.workers.add(w)         把工人添加到,工人集合里去
   2.3.t.start()              启动线程,执行worker里面的run方法
   2.4.runWorker(this)        调用外部类的runWorker()方法
   2.5.task.run()             执行任务
   2.6.getTask()              循环从队列里面去拿,如果队列里没有数据,回收非核心工人,并堵塞核心工人



3.isRunning(recheck)          判断当前线程池的生命状态是否还存在

4.offer(command)              把任务放到队列

5.addWorker(command, false)   把任务对给非核心线程

6.reject(command)             拒绝策略

    6.1.AbortPolicy           直接抛异常    
    6.2.CallerRunsPolicy      如果当前的线程池还没有关闭,直接用提交任务的线程执行任务   
    6.3.DiscardOldestPolicy   把当前队列里的队头的任务踢掉,然后把当前的任务装进去
    6.4.DiscardPolicy         空方法

线程池参数设置:

cpu密集型:cpu核数+1 io密集型:2cpu赫数+1

rocketmq,eureka,nacos 2cpu

状态转变

shutdown();running->shutdown

shutdownNow();running->stop

ScheduledThreadPoolExecutor

使用场景:分布式锁-reids

if(setnx(""))//拿到分布式锁 { 执行逻辑 }else{

park,sleep

}

Timer:单线程,线程挂了,不会再执行线程执行任务

ScheduledThreadPoolExecutor(定时线程池):线程挂了,在提交任务,线程池也会创建新的线程执行任务

xxl-job:定时任务+分布式调度

quartz:单机定时任务,功能强大

Elastic-Job