线程池是什么?线程池(ThreadPoolExecutor)使用详解-程序员宅基地

技术标签: jvm  面试  java  JavaEE初阶  java-ee  数据结构  

点一点,了解更多https://www.csdn.net/

本篇文章将详细讲解什么是线程池,线程池的参数介绍,线程池的工作流程,使用Executors创建常见的线程池~~~

目录

点一点,了解更多

文章目录

一、线程池的概念

1.1线程池的目的-提高效率

二、线程池的参数介绍

2.1线程池的拒绝策略

以上四种策略要重点掌握,面试常考~~

三、线程池的工作流程

四、线程池的创建

4.1方法一 

 4.2方法二 

4.3方法三

4.4方法四

4.5方法五

4.6方法六

4.7方法七

五、模拟实现一个线程池


一、线程池的概念

简单来说,可以理解为一个“现成的池子”,里面有一定数量的线程等待工作,每次使用不用再次创建、使用完了不用马上销毁,会自动回收进池子中。类似常量池等等~~

虽然创建销毁线程比创建销毁进程更轻量, 但是在频繁创建销毁线程的时候还是会比较低效,线程池就是为了解决这个问题,如果某个线程不再使用了,并不是真正把线程释放,而是放到一个“池子”中,下次如果需要用到线程就直接从池子中取,不用再次创建。

1.1线程池的目的-提高效率

池的目的就是为了提高效率,从线程池中拿线程,属于用户态操作;而从系统再去创建线程,涉及到用户态和内核态之间的切换,真正的创建是在内核态完成的。

那么什么是用户态?什么是内核态?下面我来举个例子:

银行中有大厅和服务柜台,大厅相当于用户态,柜台相当于内核态;每个地方都有打印机,如果来客户需要办理业务,可以在打印机上办理,也可以找工作人员办理。

此时来个老哥,说想办个银行卡,但是没带身份证复印件,有俩个办法:1.自己去大厅的复印件,自己复印一份,拿过来。2.让工作人员去柜台里面的打印机,去复印下再拿回来。

那么如果自己去复印,就立即去了,立即回来了,中间不耽误;如果工作人员去复印,他可能会做点别的,确实能给你复印,但是就不一定及时了~~

结论:用户态操作,时间是可控的;涉及到内核态操作,时间就不可控了~~

二、线程池的参数介绍

先看ThreadPoolExecutor 的构造方法

重点理解一下这几个参数含义:先情景带入一下,把线程池当作公司,一类正式员工;一类实习生;

1.corePoolSize:核心线程数,相当于正式员工

2.maxinumPoolSize:最大线程数,相当于正式员工+实习生

3.

long keepAliveTime:实习生线程保持存活的时间 

当任务比较少的时候,整体比较空闲,实习生不是立即被辞退的,表示实习生最大的存活时间

4.

TimeUnit unit:单位,秒,分钟,毫秒

5. 

BlockingQueue<Runnable> workQueue:线程池里要管理很多任务,这些任务也是通过阻塞队列来组织的,此时可以手动指定一个队列给线程池,此时就可以很方便的获取队列中的信息

6.

ThreadFactory threadFactory:工厂模式,创建线程的辅助的类

7.

RejectedExecutionHandler handler:线程池的拒绝策略,如果任务量超出公司的负荷接下来该怎么处理

2.1线程池的拒绝策略

上述四种是标准库中提供的四种拒绝策略:

1.

表示如果队列满了,继续添加任务, 添加操作之间抛出异常(新老都执行不了,哭)

2.

添加的线程自己负责执行这个任务(怼回去)

3.

丢弃最老的任务

4. 丢弃最新的任务 

以上四种策略要重点掌握,面试常考~~

三、线程池的工作流程图

四、线程池的创建

  • ExecutorService 表示一个线程池实例
  • Executors 是一个工厂类, 能够创建出几种不同风格的线程池
  • ExecutorService 的 submit 方法能够向线程池中提交若干个任务
  • Executors 本质上是 ThreadPoolExecutor 类的封装

4.1方法一 

创建具有十个线程的线程池(大小固定)

public class ThreadDemo {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
    }
}

 4.2方法二 

创建一个操作无界队列且只有一个工作线程的线程池

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

4.3方法三

用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新的线程,如果线程空闲60秒将收回并移出缓存,创建线程数目动态增长的线程池

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

4.4方法四

创建一个单线程执行器,可以在给定时间后执行或定期执行。

 ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();

4.5方法五

创建一个指定大小的线程池,可以在给定时间后执行或定期执行,是进阶版的Timer

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

4.6方法六

 创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行地处理任务,不保证处理顺序

Executors.newWorkStealingPool();

4.7方法七

自定义线程池,工作中使用这种方法创建线程池

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,
                10,
                10000,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());

五、模拟实现一个线程池

设置一个具有十个线程的线程池,打印0-1000个数。

其中在构造方法中调用十个线程执行,submit方法进行放入任务!!

class MyThreadPool{
    private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }

    public MyThreadPool(int n){
        for (int i = 0; i < n; i++) {
            Thread t = new Thread(() -> {
                try {
                    while (true){
                        Runnable runnable = queue.take();
                        runnable.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            t.start();
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool = new MyThreadPool(10);
        for (int i = 0; i < 1000; i++) {
            int number = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello "+ number);
                }
            });
        }
        Thread.sleep(3000);
    }
}

可见,线程池中任务的执行的顺序和添加顺序不一定相同,因为这十个线程是无序调度的

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/asad21654864/article/details/129800272

智能推荐

齐治堡垒机任意用户登录漏洞_/audit/gui_detail_view.php-程序员宅基地

文章浏览阅读8.7k次。声明:仅供漏洞检测和学习,勿用于非法测试漏洞披露时间2021-04-09fofa查询语法app=“齐治科技-堡垒机”POChttp://xxx.xxx.xxx.xxx/audit/gui_detail_view.php?token=1&id=%5C&uid=%2Cchr(97))%20or%201:%20print%20chr(121)%2bchr(101)%2bchr(115)%0d%0a%23&login=shterm批量检测脚本可以先用fof_/audit/gui_detail_view.php

杭电acm—1257 最少拦截系统_杭电acm1257-程序员宅基地

文章浏览阅读499次。题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1257最少拦截系统Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 43869 Accepted Submission(s)_杭电acm1257

C++可重入函数和不可重入函数_c++不可重入函数-程序员宅基地

文章浏览阅读1.8k次。C++可重入函数和不可重入函数可重入函数是指能够被多个线程“同时”调用的函数,并且能保证函数结果正确不必担心数据错误的函数。不可重入函数是指不能运行在多任务环境下,除非能保证互斥的函数。由于使用了未受保护的系统资源,如全局变量区,中断向量表等。不可重入函数在实时系统设计中被视为不安全函数。可重入函数特点:没有静态数据结构不返回指向静态数据的指针所有函数数据由函数的调用者提供使用auto变量,或通过全局变量的拷贝来保护全局变量若必须访问全局变量,则利用互斥信号保护不调用不可重入函_c++不可重入函数

微型计算机型号主要是以特征标志,安徽大学计算机教学部试题及答案-程序员宅基地

文章浏览阅读1.1k次。一、计算机基础知识1.下列叙述中,不是电子计算机特点的是_____。A.运算速度快 B.计算精度高 C.高度自动化 D.逻辑判断能力差 参考答案为:D2.现代电子计算机的本质工作原理是_____。A.能进行算术运算 B.运算速度高 C.计算精度高 D.存储并自动执行程序 参考答案为:D3.微型计算机的型号主要是以_____的型号为特征标志的。A.操作系统 B.微处理器...

chromium的部署工具depot_tools和gclient-程序员宅基地

文章浏览阅读3.6w次,点赞3次,收藏12次。depot_tools是个工具包,里面包含gclient、gcl、gn和ninja等工具。其中gclient是代码获取工具,它其实是利用了svn和git。_gclient

selenium爬虫学习,403Forbiden 获取不到价格。_selenium爬虫大众点评 403forbidden-程序员宅基地

文章浏览阅读411次,点赞12次,收藏4次。爬取速度很慢,5秒打开一个网页。部分商品详情页能获取到价格,大部分会显示403Forbiden。有了解爬虫的能指点一下嘛。_selenium爬虫大众点评 403forbidden

随便推点

InputStream只能读取一次的解决办法_inpustrem只能读一次-程序员宅基地

文章浏览阅读1w次。有时候我们需要对同一个InputStream对象使用多次。比如,客户端从服务器获取数据 ,利用HttpURLConnection的getInputStream()方法获得Stream对象,这时既要把数据显示到前台(第一次读取),又想把数据写进文件缓存到本地(第二次读取)。但第一次读取InputStream对象后,第二次再读取时可能已经到Stream的结尾了(EOFException)或者Stream_inpustrem只能读一次

webpack配置-程序员宅基地

文章浏览阅读1.1w次,点赞35次,收藏143次。webpack是前端的打包工具打包的工作内容是什么扫描项目,生成整个项目所有模块的依赖关系,根据配置对模块进行合并,生成一个单独的文件。修改html文件,让html文件引用生成后的文件将浏览器无法直接识别的(less、sass、ts)文件,转换成浏览器可以实现的内容。将浏览器暂时无法支持的JS新的语法转换成浏览器可以支持的语法。_webpack配置

Nexus 6p bootloop经历_n2g47z_4cores.img-程序员宅基地

文章浏览阅读2.2k次。昨天,用了1年半的6p不知为什么就bootloop了。正常使用中,突然就重启,然后就在重启提示和google标之间来回换,完全停不下来。能进入刷机模式,回复出场什么的都用不了,都会回到bootloop。用power off可以关机,可是一旦接上电源,就又开始bootloop。白色google一出来几秒钟不动,就感觉不对头,让人崩溃。。。。一想买新机又要花钱,决定再抢救一下了。先google..._n2g47z_4cores.img

使用JAXB进行JavaBean对象与XML文件的相互转化_jaxb 设置xml头encoding-程序员宅基地

文章浏览阅读1.7k次。思想:父标签相当于一个对象,子标签相当于对象的属性,然后循环嵌套。JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。Marshaller接口,将Java对象序列化为XML数据。Unmarshaller接口,将XML数据反序列化为Java对象。如果是第一次使用的话,建议先下载代码跑一下看看效果:https://download.csdn.net/downl..._jaxb 设置xml头encoding

泰文Unicode编码表及排版规则_泰语文字范围-程序员宅基地

文章浏览阅读1.2w次,点赞5次,收藏18次。前言:泰文Unicode编码表及排版规则泰文 Unicode字符表 泰文符号字符数量统计: 128 Unicode编码范围:0E00—0E7F代码点泰文是一个Unicode块,包含泰文、Lanna Tai和Pali语言的字符。依据泰文工业标准620-2533。范围U+0E00…U+0E7F (128 代码位)已经分配:87代码位暂未使用:41个保留位Unicode字符表字..._泰语文字范围

四、基于海思芯片:从算法到移植 生成海思wk文件并进行成果展示_华为海思芯片转wk-程序员宅基地

文章浏览阅读6.2k次,点赞5次,收藏43次。一、基于海思芯片:从算法到移植 darknet框架下训练yolov3二、基于海思芯片:从算法到移植 darknet框架下yolov3转为caffe框架下三、基于海思芯片:从算法到移植 caffe-yolov3测试训练效果四、基于海思芯片:从算法到移植 生成海思wk文件并进行成果展示好了,在家的时候把法医秦明两部剧补了一下,还看了模仿游戏讲述图灵在二战中破译密码工作,大..._华为海思芯片转wk

推荐文章

热门文章

相关标签