在并发量较高的项目中,我们往往会涉及到线程的创建与销毁的问题,由于线程的创建和销毁是很消耗我们的性能的,所以我们会在项目中引进线程池,来让我们的线程可以循环的使用,避免不停的去创建销毁线程。
线程的创建 |
ThreadPoolExecutor statsThreadPool = new ThreadPoolExecutor(
10, 10, 0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<>(200), new ThreadFactoryBuilder().build());
参数分析 |
Executors创建线程池
//创建固定数量的线程池
1. public static ExecutorService newFixedThreadPool(int nThreads)
//创建单个线程池
2. public static ExecutorService newSingleThreadExecutor()
//创建核心线程数为0的线程
3. public static ExecutorService newCachedThreadPool();
注意:当服务器资源有限时,使用newFixedThreadPool和newSingleThreadExecutor创建的线程池他的queue队列的长度是Integer.MAX_VALUE,用newCachedThreadPool创建的线程池时,他是可以创建Integer.MAX_VALUE个线程的,都会出现OOM异常。所有不是很建议大家使用,特别是在并发量大的场景中。
queue队列机制 |
- ArrayBlockingQueue: 基于数组实现,FIFO(先入先出)队列
- LinkedBlockingQueue: 基于链表实现,FIFO(先入先出)队列
- 当核心线程池的数量和最大线程数都是最大值时,就会拒绝其他的任务加入。
线程的执行和线程池的关闭 |
- 线程执行:在使用ThreadPoolExecutor线程池时,execute()方法和submit()方法都是可以执行任务的。其中submit()方法最终也是调用的是父类的execute()方法进行执行任务。
- 线程池的关闭:shutdown()方法是拒绝新的任务加入,正在执行的任务和队列中的任务会继续执行完。shutdownNow()拒绝所有新的任务加入,并且会关闭正在执行的任务且清空队列中的任务。
总结:线程池在很大层面上是提升了系统的性能,大大减少了创建和销毁线程的开销,但是大家要注意的是我们也需要合理的配置线程池中的参数。配置大了有点浪费,但配置过小性能又会差,所有需要自己多多调整自己的参数进行配置。