在开发过程中我们常常需要使用到多线程来提高我们代码处理某些任务的效率,最基本的两种创建多线程的方式分别是继承Thread类和实现Runnable接口。但是创建线程和销毁线程的系统开销比较大,而且过多的线程会占用过多的内存等资源。在《阿里巴巴Java开发手册》中也提示我们“线程资源必须通过线程池提供,不允许在应用中自行显式创建线程”。所以我们引入了线程池。
一、常见的5种线程池分别是:
1、FixedThreadPool,它的核心线程数和最大线程数是一样的,可以把它看成是固定线程数的线程池;
2、CachedThreadPool,可以把它叫做可缓存线程池,它的特点是线程数可以持续增加(理论最大可达Integer.MAX_VALUE=2^31-1);
3、ScheduledThreadPool,它支持定时或周期性的执行任务,有3个方法可以灵活的执行频率配置参数;
4、SingleThreadExecutor,它会使用唯一的线程去执行任务,适用于所有任务都需要按照被提交的顺序依次执行的场景;
5、SingleThreadScheduledExecutor,它和SingleThreadExecutor有些类似,它的核心线程数是1,但是最大线程数是Integer.MAX_VALUE。
二、创建方法:
使用 Executors 去创建,这个些线程池对应的方法都是静态的,例:
Executors.newFixedThreadPool(10);
三、参数对比:
参数 | FixedThreadPool | CachedThreadPool | ScheduledThreadPool | SingleThreadExecutor | SingleThreadScheduledExecutor |
corePoolSize | 构造函数传入 | 0 | 构造函数传入 | 1 | 1 |
maxPoolSize | 同corePoolSize | Integer.MAX_VALUE | Integer.MAX_VALUE | 1 | Integer.MAX_VALUE |
keepAliveTime | 0 | 60s | 0 | 0 | 0 |
workQueue | LinkedBlockingQueue | SynchronousQueue | DelayedWorkQueue | LinkedBlockingQueue | DelayedWorkQueue |
当我们去看这些线程池的实现的时候,会发现它们最终都创建ThreadPoolExecutor对象,也就是说上面的这5个线程池只是对ThreadPoolExecutor做了一层封装而已,让他们适用一些特定的场景。在《阿里巴巴Java开发手册》中提示我们“线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险”。所以我们在实际创建线程池的时候一般都是通过ThreadPoolExecutor这种方式。