没用线程池的我,被上司一jio!

沙海 2021年8月25日05:08:30Java评论30字数 4717阅读15分43秒阅读模式
摘要

智能摘要

智能摘要文章源自JAVA秀-https://www.javaxiu.com/42166.html

前天指北君的朋友小B,他写了一个汇总的业务,用了很多的线程就是没用到线程池,被上司一顿批。代表线程池的接口,有一个execute()方法,给一个Runnable类型对象就可以分配一个线程执行。判断线程池里的线程达到了最大线程数maximumPoolSize,如果没有,则创建一个新的线程来执行任务。线程池的创建需要有7个参数,还是比较复杂的,JVM为我们提供了Executors类中多个静态工厂,生成一些常用的线程池。文章源自JAVA秀-https://www.javaxiu.com/42166.html

原文约 1481 | 图片 8 | 建议阅读 3 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!

纯洁的微笑 文章源自JAVA秀-https://www.javaxiu.com/42166.html

以下文章来源于Java技术指北,作者指北君文章源自JAVA秀-https://www.javaxiu.com/42166.html

文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

Java技术指北文章源自JAVA秀-https://www.javaxiu.com/42166.html

回复:java,获取精华资料。专注分享Java技术干货、Java 技术、Spring 全家桶、JavaWeb、多线程、JVM、Spring Boot、Spring Cloud、Dubbo、架构设计、微服务、面试题、Java最新动态等。文章源自JAVA秀-https://www.javaxiu.com/42166.html

文章源自JAVA秀-https://www.javaxiu.com/42166.html

大家好,我是指北君。文章源自JAVA秀-https://www.javaxiu.com/42166.html

前天指北君的朋友小 B,他写了一个汇总的业务,用了很多的线程就是没用到线程池,被上司一顿批。那一起来看看,线程池是什么吧?文章源自JAVA秀-https://www.javaxiu.com/42166.html

线程池是用来统一管理线程的,在 Java 中创建和销毁线程都是一件消耗资源的事情,线程池可以重复使用线程,不再频繁的创建、销毁线程。文章源自JAVA秀-https://www.javaxiu.com/42166.html

初识

Java 中的线程池是由 juc 即 java.util.concurrent 包来实现的,最主要的就是 ThreadPoolExecutor 类。文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

  1. Executor: 代表线程池的接口,有一个 execute() 方法,给一个 Runnable 类型对象就可以分配一个线程执行。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  2. ExecutorService:是 Executor 的子接口,提供了线程池的一些生命周期方法。代表了一个线程池管理器。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  3. ThreadPoolExecutor:一个线程池的实现类,可以通过调用 Executors 静态工厂方法来创建线程池并返回一个 ExecutorService 对象。文章源自JAVA秀-https://www.javaxiu.com/42166.html

ThredadPoolExcutor

看一下最常用的 ThredadPoolExcutor ,下图是 ThreadPoolExecutor 的构造函数文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

从源码中可以看出每个前三个构造函数都调用了最后一个构造函数。文章源自JAVA秀-https://www.javaxiu.com/42166.html

public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue,                              ThreadFactory threadFactory,                              RejectedExecutionHandler handler) {    //省略代码    }

仔细分析一下构造参数:文章源自JAVA秀-https://www.javaxiu.com/42166.html

  1. corePoolSize:线程池里的核心线程数量,当正在运行的线程数量小于核心线程数量,就创建一个核心线程。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  2. maximumPoolSize:线程池最多能放多少个线程。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  3. keepAliveTime:线程的闲置时间,当线程池里面的线程数量大于 corePoolSize 的时候,多出来的线程在等待的时间之后会被释放掉文章源自JAVA秀-https://www.javaxiu.com/42166.html

  4. unit:keepAliveTime 的单位文章源自JAVA秀-https://www.javaxiu.com/42166.html

  5. workQueue:一个阻塞队列。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  6. threadFactory:通过这个工厂模式创建线程。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  7. handler:处理线程队列满了报错的。文章源自JAVA秀-https://www.javaxiu.com/42166.html

结合线程池的参数简单的画出线程池的工作模型。文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

当线程池中的核心线程数量 corePoolSize 满了,就会将任务先加入到任务队列 workQueue 中。文章源自JAVA秀-https://www.javaxiu.com/42166.html

执行过程

线程池的执行过程如下图:文章源自JAVA秀-https://www.javaxiu.com/42166.html

  1. 首先判断核心线程 corePoolSize 是不是满了,如果没有满,就执行任务,否则就进入下一步。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  2. 线程池判断任务队列 workQueue 是否了,如果没有满,则将新提交的任务放入在这个任务队列里。如果任务队列满了,则进入一步。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  3. 判断线程池里的线程达到了最大线程数 maximumPoolSize,如果没有,则创建一个新的线程来执行任务。如果已经满了,则交给拒绝策略来处理这个任务。文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

常用的线程池

线程池的创建需要有 7 个参数,还是比较复杂的,JVM 为我们提供了 Executors 类中多个静态工厂,生成一些常用的线程池。文章源自JAVA秀-https://www.javaxiu.com/42166.html

SingleThreadExecutor

单线程的线程池,里面就一个核心线程数。文章源自JAVA秀-https://www.javaxiu.com/42166.html

public static ExecutorService newSingleThreadExecutor() {    return new FinalizableDelegatedExecutorService        (new ThreadPoolExecutor(1, 1,                                0L, TimeUnit.MILLISECONDS,                                new LinkedBlockingQueue<Runnable>()));}

ThreadPoolExecutor 参数只有一个核心线程数和一个最大线程数,这个很少用到。它保证了所有线程的执行顺序都是按照提交到线程池的顺序执行。文章源自JAVA秀-https://www.javaxiu.com/42166.html

public class TodoDemo implements Runnable {    public static void main(String[] args) {        ExecutorService executorService = Executors.newSingleThreadExecutor();        for(int i = 0; i < 10; i++) {            executorService.execute(new TodoDemo());        }        executorService.shutdown();    }    @Override    public void run() {        System.out.println(Thread.currentThread().getName() + " Running");    }}

只有一个线程在跑。文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

FixedThreadExecutor

固定数量的线程池文章源自JAVA秀-https://www.javaxiu.com/42166.html

    return new ThreadPoolExecutor(nThreads, nThreads,                                    0L, TimeUnit.MILLISECONDS,                                    new LinkedBlockingQueue<Runnable>());}

这个线程池的特点就是线程的数量是固定的,超过这个数量的任务就得在 LinkedBlockingQueue 中排队等候。文章源自JAVA秀-https://www.javaxiu.com/42166.html

public class TodoDemo implements Runnable {        public static void main(String[] args) {        ExecutorService executorService = Executors.newFixedThreadPool(3);        for(int i = 0; i < 10; i++) {            executorService.execute(new TodoDemo());        }        executorService.shutdown();    }    @Override    public void run() {        System.out.println(Thread.currentThread().getName() + " Running");    }}

可以看到就算提交 100 个任务也只有 3 个线程。文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

CachedThreadExecutor

自动回收空闲的线程文章源自JAVA秀-https://www.javaxiu.com/42166.html

public static ExecutorService newCachedThreadPool() {    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                    60L, TimeUnit.SECONDS,                                    new SynchronousQueue<Runnable>());}

可以看到核心线程数量为 0, 表示不会永久保留任何的线程,最大线程的数量是 Integer.MAX_VALUE,可以无限制的创建线程,但是当有大量线程处于空闲状态的时候,超过 60s 就会被销毁。文章源自JAVA秀-https://www.javaxiu.com/42166.html

public class TodoDemo implements Runnable {    public static void main(String[] args) {        ExecutorService executorService = Executors.newCachedThreadPool();        for(int i = 0; i < 20; i++) {            executorService.execute(new TodoDemo());        }        executorService.shutdown();    }    @Override    public void run() {        System.out.println(Thread.currentThread().getName() + " Running");    }}

虽然这个线程池可以想建多少个线程就建多少个线程,但是还是会重用已经完成任务的线程。文章源自JAVA秀-https://www.javaxiu.com/42166.html

没用线程池的我,被上司一jio!文章源自JAVA秀-https://www.javaxiu.com/42166.html

一般最常用的是FixedThreadExecutor和CachedThreadExecutor。文章源自JAVA秀-https://www.javaxiu.com/42166.html

线程池的回收策略

在线程池中任务队列已经满了,并且线程的数量已经到了最大的数量,这个时候再加任务线程池就不再接受了。文章源自JAVA秀-https://www.javaxiu.com/42166.html

在 ThreadPoolExecutor 里有 4 种拒绝策略,都实现了 RejectedExecutionHandler:文章源自JAVA秀-https://www.javaxiu.com/42166.html

  1. AbortPolicy 表示抛出一个异常。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  2. DiscardPolicy 拒绝任务但是不提示。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  3. DiscardOldestPolicy 丢弃掉老的任务,执行新的任务。文章源自JAVA秀-https://www.javaxiu.com/42166.html

  4. CallerRunsPolicy 直接调用线程处理。文章源自JAVA秀-https://www.javaxiu.com/42166.html

总结

线程池的作用是提高系统的性能和线程的利用率,不再需要频繁的创建和销毁线程。如果使用最简单的方式创建线程,在用户量巨大的情况下,消耗的性能是非常恐怖的,所以才有了线程池。文章源自JAVA秀-https://www.javaxiu.com/42166.html

我是指北君,操千曲而后晓声,观千剑而后识器。感谢各位人才的:点赞、收藏和评论,我们下期更精彩!文章源自JAVA秀-https://www.javaxiu.com/42166.html

最近又赶上跳槽的高峰期,好多粉丝,都问我要有没有最新面试题,我连日加班好多天,终于整理好了,16000+ 道,295多份,多份面试题大全,我会持续更新中,马上就会整理更多!文章源自JAVA秀-https://www.javaxiu.com/42166.html

公众号回复面试题】即可获取文章源自JAVA秀-https://www.javaxiu.com/42166.html

文章源自JAVA秀-https://www.javaxiu.com/42166.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定