栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JUC —— 线程池

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JUC —— 线程池

池化技术

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

线程池

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

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

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


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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/732255.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号