基础问题,不涉及锁相关的知识
线程池7大参数:
corePoolSize:核心线程数,线程池中始终存活的线程数。
maximumPoolSize:最大线程数,线程池中允许的最大线程数,当线程池的任务队列满了之后可以创建的最大线程数。
keepAliveTime:指的是空闲线程存活时间。具体说,当线程数大于核心线程数时,空闲线程在等待新任务到达的最大时间,如果超过这个时间还没有任务请求,该空闲线程就会被销毁。
unit:空闲线程存活时间的单位。keepAliveTime的计量单位。枚举类型TimeUnit类。
workQueue:一个阻塞队列,用来存储线程池等待执行的任务,均为线程安全。
threadFactory:线程工厂,主要用来创建线程
1)synchronousQueue:无缓冲等待队列,是一个不存储的元素阻塞队列,当有任务且最大线程数未满的时候,直接创建线程执行。
2)ArrayBlockingQueue:有界缓存队列,可以指定缓存数量,当超出缓存数量且最大线程数未满的时候,会创建线程执行。
3)LinkedBlockingQueue:无界缓冲队列,剩余的元素会在阻塞队列中等待,只会创建corePoolSize个线程
handler:拒绝策略,拒绝处理任务时的策略(重点)
策略1:ThreadPoolExecutor.AbortPolicy(默认)
在默认的处理策略。该处理在拒绝时抛出RejectedExecutionException,拒绝执行。
策略2:ThreadPoolExecutor.CallerRunsPolicy
调用 execute 方法的线程本身运行任务。这提供了一个简单的反馈控制机制,可以降低新任务提交的速度。将多出来的任务退还给调用者,从而降低流量。
策略3:ThreadPoolExecutor.DiscardOldestPolicy
抛弃等待队列中等待最久的任务,然后把当前任务加入等待队列。
策略4:ThreadPoolExecutor.DiscardPolicy
无法执行的任务被简单地删除,将会丢弃当前任务,通过源码可以看出,该策略不会执行任务操作。
怎么设置线程数量
CPU密集型任务尽量使用较小的线程池,一般为CPU核心数+1。
因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,只能增加上下文切换的次数,因此会带来额外的开销。
IO密集型任务可以使用稍大的线程池,一般为2*CPU核心数+1。
因为IO操作不占用CPU,不要让CPU闲下来,应加大线程数量,因此可以让CPU在等待IO的时候去处理别的任务,充分利用CPU时间。
除了进程和线程,你了解过协程吗
协程是一种用户级的轻量级线程。协程拥有自己的寄存器上下文和栈
协程运行在线程之上,当一个协程执行完成后,可以选择主动让出,让另一个协程运行在当前线程之上。协程并没有增加线程数量,只是在线程的基础之上通过分时复用的方式运行多个协程,而且协程的切换在用户态完成,切换的代价比线程从用户态到内核态的代价小很多.