线程池了解么?
首先说一下线程实现方法中,实现 Runnable 接⼝和 Callable 接⼝的区别?
Runnable接口不会返回结果以及抛出异常,但是Callable是可以的,所以如果任务不需要返回结果或抛出异常推荐使⽤ Runnable 接⼝,这样代码看起来会看起来更加简洁。
为什么要⽤线程池?
1、降低资源消耗。通过重复利⽤已创建的线程降低线程创建和销毁造成的消耗。
2、提⾼响应速度。当任务到达时,任务可以不需要的等到线程创建就能⽴即执⾏。
3、提⾼线程的可管理性。线程是稀缺资源,如果⽆限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使⽤线程池可以进⾏统⼀的分配,调优和监控。
创建线程池的方式?
提倡使用ThreadPoolExecutor 的⽅式,而不使用Executor的方式,主要是因为后者可能会出现以下情况:
对于FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列⻓度为Integer.MAX_VALUE ,可能堆积⼤量的请求,从⽽导致 OOM。
而对于CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为Integer.MAX_VALUE ,可能会创建⼤量线程,从⽽导致 OOM。
ThreadPoolExecutor 类分析:
/** * ⽤给定的初始参数创建⼀个新的ThreadPoolExecutor。 */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
下面是几个线程池中最重要的参数:
corePoolSize : 核⼼线程数线程数定义了最⼩可以同时运⾏的线程数量。
maximumPoolSize : 当队列中存放的任务达到队列容量的时候,当前可以同时运⾏的线程数量变为最⼤线程数。
workQueue : 当新任务来的时候会先判断当前运⾏的线程数量是否达到核⼼线程数,如果达到的话,新任务就会被存放在队列中。
keepAliveTime :当线程池中的线程数量⼤于 corePoolSize 的时候,如果这时没有新的任务提交,核⼼线程外的线程不会⽴即销毁,
⽽是会等待,直到等待的时间超过了keepAliveTime 才会被回收销毁;
unit : keepAliveTime 参数的时间单位。
threadFactory :executor 创建新线程的时候会⽤到。
handler :饱和策略。也叫拒绝策略。