前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java-线程池面试题

Java-线程池面试题

作者头像
全栈程序员站长
发布2022-09-01 14:25:54
1930
发布2022-09-01 14:25:54
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

线程池

前言

线程池在面试、开发过程中都比较重要。本文总结了一些关于该方面的相关知识点。 以下内容收集于 蚂蚁课堂

什么是线程池

线程池和数据库连接池非常类似,可以统一管理和维护线程,减少没有必要的开销。

为什么要使用线程池

因为在项目开发过程中频繁的开启线程或者停止线程,线程需要重新被CPU从就绪状态调度到运行状态,需要发生CPU的上下文切换,效率非常低。

线程的生命周期如下图所示:

在这里插入图片描述
在这里插入图片描述

线程池有哪些作用

  • 降低资源消耗:通过池化技术重复利用已创建好的线程,降低线程创建和销毁造成的损耗。
  • 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
  • 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
  • 提供更多强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延迟定时线程池 ScheduledThreadPoolExecutor ,就允许任务延期执行或定期执行。

线程池的创建方式

分为以下几种创建方式:

  • Executors.newCachedThreadPool():可缓存线程池
  • Executors.newFixedThreadPool():可定长度,限制最大线程数
  • Executors.newScheduledThreadPool():可定时线程池
  • Executors.newSingleThreadExecutor():单例线程池 底层都是基于 ThreadPoolExecutor 构造函数封装

如何实现复用

本质思想:创建一个线程,不会立马体质或者销毁,而是一直实现复用。

  • 提前创建固定大小的线程一直保持正在运行的状态(可能会非常消耗CPU资源)。
  • 当需要线程执行任务,将该任务提交缓存在并发队列中,如果缓存队列满了,则会执行拒绝策略。
  • 正在运行的线程从并发队列中获取任务执行从而实现线程复用的问题。 线程池底层原理如下图所示:
在这里插入图片描述
在这里插入图片描述

线程池核心点:复用机制

  • 提前创建好固定的线程一直在运行状态—死循环实现。
  • 提交的线程任务缓存到一个并发队列集合中,交给我们正在运行的线程执行。
  • 正在运行的线程就从队列中获取该任务执行。

简单实现代码如下:

代码语言:javascript
复制
/** * @author zfl_a * @date 2021/3/20 * @project multi-thread */
public class CustExcutors { 
   

    // 存放线程任务
    public BlockingDeque<Runnable> runnableList ;

    // 停止线程标识位
    private volatile Boolean isRun = true ;

    /** * 初始化 * @param dequeSize 队列容器大小 * @param threadCount 线程池大小 */
    public CustExcutors(int dequeSize,int threadCount){ 
   
        runnableList = new LinkedBlockingDeque<>(dequeSize);
        for (int i=0;i<threadCount;i++) { 
   
            WorkThread workThread = new WorkThread();
            workThread.start();
        }
    }

    public void execute(Runnable runnable){ 
   
        runnableList.offer(runnable);
    }

    class WorkThread extends Thread { 
   

        @Override
        public void run (){ 
   
            // 标识位位true 或者队列中有未执行完成的任务
            while(isRun || runnableList.size()>0) { 
   
                Runnable runnable = runnableList.poll();
                // 如果不为空 ,执行
                if(runnable!=null) { 
   
                    runnable.run();
                }
            }
        }
    }

    public static void main(String[] args) { 
   
        CustExcutors custExcutors = new CustExcutors(10,2);
        for (int x=0;x<10;x++) { 
   
            final int i = x ;
            custExcutors.execute(new Runnable() { 
   
                @Override
                public void run() { 
   
                    System.out.println(Thread.currentThread().getName()+"----"+i);
                }
            });
        }
        // 停止线程
        custExcutors.isRun=false;
    }
}

运行结果:只有两个线程在运行任务

在这里插入图片描述
在这里插入图片描述

ThreadPoolExecutor核心参数

  • corePoolSize:核心线程数量,一直正在保持运行的线程。
  • maximumPoolSize:最大线程数,线程池允许创建的最大线程数。
  • keepAliveTime:超出 corePoolSize 后创建的线程存活时间(当超过核心线程数后,又没有线程任务执行,达到该存活时间后,停止该线程)。
  • unit:keepAliveTime 的时间单位。
  • workQueue:任务队列,用于保持待执行的任务。
  • threadFactory :线程池内部创建线程所用的工厂。
  • handler:任务无法执行时的处理器(当任务被拒绝时)。

其他相关总结

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/141560.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 线程池
  • 前言
  • 什么是线程池
  • 为什么要使用线程池
  • 线程池有哪些作用
  • 线程池的创建方式
  • 如何实现复用
  • ThreadPoolExecutor核心参数
  • 其他相关总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档