线程池分类
newCachedThreadPool
创建可缓存的线程池,根据需要创建,以前存在重用他们
newFixedThreadPool
创建固定的线程池,可重用
newScheduledThredPool
创建一个线程池,安排计划执行(定期)
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("等3秒");
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("延迟一秒后每三秒执行一次");
}
}, 1, 3, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(() -> {
System.out.println("===============");
}, 1, 3, TimeUnit.SECONDS);
}
结果
延迟一秒后每三秒执行一次
===============
等3秒
延迟一秒后每三秒执行一次
===============
延迟一秒后每三秒执行一次
===============
延迟一秒后每三秒执行一次
===============
延迟一秒后每三秒执行一次
===============
newSingleThreadExecutor
单例执行,这个线程池只有一个线程,这个线程可以在线程异常后重启一个线程替代原来线程继续去执行
如何合理设置线程池大小
线程是一种稀缺的资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性
资源与稳定性对我们都很重要。
我们要考虑到实际情况,甚至有的时候测试花环境通常资源少,性能低;生产环境资源多,性能强。要充分考虑到任务的性质、优先级、是否核心功能、任务的执行时间、依赖性。
任务的性质:CPU密集型任务、IO密集型任务、混合型任务。
任务的优先级:高、中、低。
任务的执行时间:长、中、短。
任务的依赖性:是否依赖其他系统资源,如数据库连接等。
性质不同的任务可以交给不同规模的线程池执行。
网上有一个推演合适的公式:
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1) CPU数目*
线程等待时间所占比例越高,需要线程池越大。线程CPU时间所占比例越高,需要越线程池越小。