使用线程池的益处
- 避免重复创建线程执行任务,减少了创建线程和销毁线程需要的时间开销和性能开销;
- 提高任务响应速度,线程池中通常缓存有线程,当提交任务以后,可迅速执行;
- 避免了无规则的创建大量线程,导致大量线程排队等待CPU,响应速度变慢;
线程池处理流程
我们可以调用线程池的execute和submit方法来提交任务,提交参数都是一个Runnable实例,不同的是,submit会返回一个Future类型的对象,可以通过future对象的get方法获得返回值,注意这个方法会阻塞当前线程。
- 当一个任务提交给线程池时,如果当前线程池中线程数量少于核心线程数,会重新创建新的线程执行这个任务,然后通过线程安全的方法更新当前线程数。注意,当提交一个任务给线程池时,线程池会创建一个核心线程来执行,即使其他核心线程空闲,直到核心线程达到预设值。
- 如果当前线程数已经大于或者等于核心线程数,那会尝试判断阻塞队列是否已满,未满的话将任务加入到阻塞队列中。
- 已满则判断当前线程池数量是否小于最大线程数量,如果是的话,创建工作线程执行,否则的话执行拒绝策略。
线程池参数说明
1 | public ThreadPoolExecutor(int corePoolSize,//核心线程数 |
阻塞队列有很多种,newCachedThreadPool使用SynchronousQueue,这种阻塞队列不存储任务,每个插入操作必须等待一个线程执行取出操作,否则插入线程阻塞。newFixedThreadPool则使用LinkedBlockingQueue。
拒接策略分为四种,分别是直接只用调用者所在线程执行任务、直接抛出异常、丢弃队列里等待最长时间的任务,执行当前任务、或者直接丢弃掉当前任务。
配置线程池
根据不同的情况配置线程池:
- 根据任务性质,比如是CPU密集型还是IO密集型,CPU密集型应该配置尽可能少的线程,防止线程持续等待CPU分配时间,IO密集型就可以多一些线程,因为大部分线程可能在等待IO;
- 任务优先级,是否有些任务是高优执行的,可以使用ProrityQueue作为阻塞队列。