程序的运行,本质:占用系统的资源,优化资源的使用 =>池化技术
线程池、连接池、内存池、对象池… 创建和销毁十分浪费资源
池化技术:事先准备好一些资源,有人要用就来这里拿,用完了在还回来
线程池的好处: 线程复用、可以控制最大并发数、管理线程
降低资源的消耗提高响应的效率方便管理
三大方法、七大参数、四种拒绝策略
三大方法
Executors.newSingleThreadExecutor(); //单个线程的线程池 Executors.newFixedThreadPool(5); //给定大小的线程池 Executors.newCachedThreadPool(); //无限大小的线程池
public class 三大方法 { //使用了线程池之后,使用线程池来创建线程 public static void main(String[] args) { ExecutorService executorService = null; Executors.newSingleThreadExecutor();//单个线程的线程池 Executors.newFixedThreadPool(5); //给定大小的线程池 Executors.newCachedThreadPool(); //无限大小的线程池 for (int i = 1; i <= 10; i++) { executorService.execute(()->{ System.out.println(Thread.currentThread().getName()+"执行"); }); } }}
executorService = Executors.newSingleThreadExecutor();//单个线程的线程池
执行结果:
pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行
从结果可以看出: Executors.newSingleThreadExecutor() 是创建的单个线程
executorService = Executors.newFixedThreadPool(5); //给定大小的线程池
执行结果:
pool-2-thread-1执行pool-2-thread-1执行pool-2-thread-1执行pool-2-thread-1执行pool-2-thread-1执行pool-2-thread-1执行pool-2-thread-2执行pool-2-thread-3执行pool-2-thread-4执行pool-2-thread-5执行
从结果可以看出: Executors.newFixedThreadPool(5) 最大线程数是根据我们自己定的数量来创建
executorService = Executors.newCachedThreadPool(); //无限大小的线程池
执行结果:
pool-3-thread-1执行pool-3-thread-2执行pool-3-thread-3执行pool-3-thread-4执行pool-3-thread-5执行pool-3-thread-6执行pool-3-thread-7执行pool-3-thread-8执行pool-3-thread-9执行pool-3-thread-10执行
从结果可以看出:Executors.newCachedThreadPool() 是根据cpu来决定创建多少个线程的
七大参数
三大方法源码分析:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new linkedBlockingQueue
可以发现,三大方法底层都是new了一个ThreadPoolExecutor
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小 int maximumPoolSize, //最大核心线程池大小 long keepAliveTime, //超时了没有人调用就会释放 TimeUnit unit, //超时时间单位 BlockingQueue
ThreadPoolExecutor.AbortPolicy():默认的拒绝策略,超出线程数最大承载量的请求会被驳回并抛出异常ThreadPoolExecutor.CallerRunsPolicy():哪来的去哪,超出部分谁发起的请求,谁执行ThreadPoolExecutor.DiscardPolicy():超出了会丢掉任务,但不会抛出异常ThreadPoolExecutor.DiscardOldestPolicy():尝试和最早的线程竞争,如果没竞争过则会被丢弃,不会抛出异常 手动创建线程池
//创建了一个核心线程大小为2,最大核心线程大小为5,超时时间为3秒,阻塞队列容量为3,使用默认线程工厂和默认拒绝策略的线程池 ExecutorService threadPool = new ThreadPoolExecutor( 2, 5, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
最大核心线程池大小到底该如何定义?CPU密集型:电脑是几核的就可以设置多大,cpu的核数可以通过代码获取Runtime.getRuntime().availableProcessors(),可以在创建线程池的时候直接通过该命令设置最大核心线程池大IO密集型:判断程序中有多少十分耗IO的线程,一般会设置这个数量的两倍