欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

JUC——线程池

时间:2023-07-05
池化技术

程序的运行,本质:占用系统的资源,优化资源的使用 =>池化技术
线程池、连接池、内存池、对象池… 创建和销毁十分浪费资源
池化技术:事先准备好一些资源,有人要用就来这里拿,用完了在还回来

线程池

线程池的好处: 线程复用、可以控制最大并发数、管理线程

降低资源的消耗提高响应的效率方便管理

三大方法、七大参数、四种拒绝策略


三大方法

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())); } public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new linkedBlockingQueue()); }public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }

可以发现,三大方法底层都是new了一个ThreadPoolExecutor
ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize, //核心线程池大小 int maximumPoolSize, //最大核心线程池大小 long keepAliveTime, //超时了没有人调用就会释放 TimeUnit unit, //超时时间单位 BlockingQueue workQueue, //阻塞队列 ThreadFactory threadFactory, //线程工厂,创建线程的,一般不用动 RejectedExecutionHandler handler //拒绝策略) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }

参数解释corePoolSize核心线程池大小,可以理解为一般情况下池中维护线程的数量maximumPoolSize最大核心线程池大小,可以理解为线程池中可维护的可执行的最大线程数量keepAliveTime超时时间,可以理解为超出了核心线程池大小的线程,在超时时间内没有被使用,超出超时时间后就会被释放掉TimeUnit超时时间单位BlockingQueue阻塞队列,举例说明:核心线程池大小是2个,当请求线程有5个时,超出核心线程池大小的3个会进入到BlockingQueue阻塞队列中等待,设置阻塞队列的容量,如果在阻塞队列中等待的请求超过了阻塞队列的容量,那么就会在线程数最大承载量的范围内创建新的线程ThreadFactory线程工厂,创建线程的RejectedExecutionHandler拒绝策略,当线程请求超过了线程数最大承载(最大核心线程池大小+阻塞队列容量),超出部分执行拒绝策略四种拒绝策略

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的线程,一般会设置这个数量的两倍

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。