多线程学习-线程池

目录

1.线程池的作用

2.线程池的实现

3.自定义创建线程池


1.线程池的作用

        当我们使用Thread的实现类来创建线程并调用start运行线程时,这个线程只会使用一次并且执行的任务是固定的,等run方法中的代码执行完之后这个线程就会变成垃圾等待被回收掉。如果是使用实现Runnable接口或者使用实现Callable接口先创建一个任务类,再将任务传递给创建的线程,那这个线程虽然可以用来执行不同的任务,只需要将不同的任务类对象传递给这个线程即可,但仍旧无法解决线程使用的一次性问题。我们希望一个线程不仅是能够通用的,而且还是能够复用的,这就需要线程池来帮忙。

        线程池顾名思义就是一个存放线程的池子,当执行一个任务需要线程时就从里面取出一个,用完之后再还回线程池。其特点是:

  • 初始状态下线程池是空的,里面没有线程,需要线程时才会创建线程。
  • 当线程池创建的线程数还没有达到线程池的容量时,如果有任务需要一个线程但线程池中没有空闲线程,线程池会重新创建一个线程放到线程池中。
  • 当线程池创建的线程数达到线程池的容量时,即使线程池中没有空闲线程也不会继续创建,这时那些需要线程的任务会进入一个等待队列,等到其他任务归还线程后才能根据先到先得的原则获取线程。
  • 当任务执行完毕后所使用的线程会归还给线程池,此时这个线程又变成空闲线程。

2.线程池的实现

        线程池有两种,一种是无限线程池,理论上线程池的容量是无限的,实际上其最大容量为int的最大范围,但由于实际生活中创建一个int范围的线程基本上不能实现,并且也无法同时运行这么多的线程,所以可以说是无限的;另一种则是有限线程池,在创建时需要指定容量。

        代码实现:

//实现Runnable接口创建的任务类
public class MyRun implements Runnable{@Overridepublic void run() {for(int i=0;i<100;i++)System.out.println(Thread.currentThread().getName()+"正在执行MyRun的任务,输出"+i);}
}//实现Callable接口创建的任务类
public class MyCall implements Callable<String> {@Overridepublic String call() throws Exception {return Thread.currentThread().getName()+"正在执行MyCall的任务";}
}//使用线程池
public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {//无限线程池的创建ExecutorService pool= Executors.newCachedThreadPool();//有限线程池的创建ExecutorService pool1=Executors.newFixedThreadPool(3);//创建两种类型的任务类Runnable r=new MyRun();Callable<String> c=new MyCall();FutureTask<String> ft=new FutureTask<String>(c);//提交任务,提交之后就会向线程池申请线程并执行任务pool1.submit(r);//由于Callable类型的任务的返回值需要FutureTask管理,所以提交的是ftpool1.submit(ft);System.out.println(ft.get());//销毁线程池pool1.shutdown();pool.shutdown();}
}

        运行结果:

        这里可以发现线程池创建的线程是以“pool-线程池编号-thread-线程编号”来命名的。线程池和所创建的线程的编号都是从1开始,可以查看源码:

         在上面的例子中,有限线程池设置的容量为3,但只提交了两个任务,所以不会出现有任务获取不到线程而进入等待队列的情况。

        下面测试进入等待队列的情况,提交4个Runnable类型的任务,因为一个任务要循环100次输出耗时较长,可以在提交第四个任务时保证线程池中没有空闲线程,然后让其进入等待队列。利用Debug来查看是否有任务进入了等待队列,先准备好测试代码并加上断点:

        开始调试,线程池在创建后可以看到它的属性:

        下面执行提交第一个任务:

         提交第二个任务:

        提交第三个任务:

        提交第四个任务:

        补充:在实际情况下服务器通常都是一直工作,所以线程池会一直被使用,就没有必要销毁掉,所以一般情况下不会用到销毁操作。

3.自定义创建线程池

        一个线程池所创建的线程分为核心线程和临时线程,核心线程则是在创建后会一直存在,直到线程池关闭,而临时线程则是当提交的任务过多时应急使用的,临时线程也会正常工作,但在工作结束后如果在一定时间内没有其他任务,则会被销毁。要注意的是,只有当等待队列的任务占满了整个队列,后面再提交任务时才会创建临时线程,并且创建的临时线程处理的任务并不是等待队列中的任务,而是队列满后后面再提交的任务。如果创建的临时线程达到最大数量,此时仍有任务被提交时就需要选择一种应对策略来处理后面提交的任务。

        自定义线程池需要设置以下七种参数:

  • 允许创建的最大核心线程数量(不能小于0)
  • 允许创建的最大线程数量(不能小于0且必须>=核心线程数量,最大线程数量减去最大核心线程数量就是可以创建的最大临时线程数量)
  • 临时线程的最大空闲时间1(设置时间的值,不能小于0)
  • 临时线程的最大空闲时间2(设置时间的单位,使用TimeUnit指定)
  • 等待队列(其实就是一个阻塞队列,不能为null)
  • 创建线程的工厂(也就是怎样创建一个线程,不能为null)
  • 应对策略(一共有四种策略,四选一,一般选择第一个,不能为null)

         自定义创建线程池代码实现:

//创建自定义线程池
ThreadPoolExecutor pool2=new ThreadPoolExecutor(3, //设置核心线程的最大创建数量5, //设置最大线程数量(最大临时线程数量也就是5-3=2)60, //设置临时线程的最大空闲时间的值部分TimeUnit.SECONDS, //设置临时线程的最大空闲时间的单位部分new ArrayBlockingQueue<>(5), //加入阻塞队列作为等待队列Executors.defaultThreadFactory(), //使用java提供的线程池默认创建线程的工厂作为创建线程的工厂即可new ThreadPoolExecutor.AbortPolicy() //选择第一种应对策略,AbortPolicy是一个内部类);

        使用方式和普通线程一样,提交任务用submit,销毁用shutdown。

        补充内部类:内部类是在一个类中定义另一个类。当这个类需要依附于另一个类但这个类本身也是独立的一部分时可以将这个类创建为其他类的内部类,就比如发动机和汽车,发动机需要依附于汽车才能发挥作用,但发动机本身又是独立的一部分。

        那线程池的最大线程数量是不是越大越好呢?其实不然,线程池的最大线程数量通常是按照规定来的,这取决于开发的项目是CPU密集型还是I/O密集型的。

        CPU密集型也就是所开发的项目需要进行的运算偏多,而执行运算操作就要用到CPU。这种项目所需的最大线程数量应当设置为:最大并行数+1

        所谓最大并行数就是看CPU能最多能分给java多少线程,通常说CPU是多少核多少线程的,核数就是这个CPU有多少大脑,多少线程就是这个CPU有多少只手,每只手对应一个线程,但不一定所有的线程都可以让java调度,我们可以通过下面的代码查看可以分给java的最大线程数:

//查看CPU能分给java的最大线程数
int num=Runtime.getRuntime().availableProcessors();
System.out.println(num);

        可以分配给java的最大线程数就是最大并行数,至于要加1是为了当已经创建了的某个线程出现问题时可以利用这个多出来的线程继续工作, 尽可能地将CPU利用率最大化。

        I/O密集型就是开发的项目中I/O操作比较多,现在大多数项目都是I/O密集型的。这种情况下线程池的最大线程数量可以设置为:最大并行数*期望CPU的利用率*(总的运行时间/CPU的运行时间)。通常情况下我们希望CPU的利用率越高越好,所以可以设置为100%,最大并行数在CPU密集型部分介绍过了,那什么是CPU的运行时间呢?

        比如要执行读取文件中的两个整数并相加的操作,这个操作分为两部分,从文件中读取数据的部分没有用到CPU,而后面的相加部分属于运算,就需要CPU了。所以在这个例子中,CPU的运行时间就是后面相加所需的时间。在实际项目中可以使用thread dump工具来测总的运行时间和CPU的运行时间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/595587.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue2(十三):Vuex环境搭建、Vuex工作原理、几个配置项、多组件共享数据、Vuex模块化

一、Vuex 1.理解 1.概念&#xff1a;专门在Vue中实现集中式状态(数据&#xff09;管理的一个Vue插件&#xff0c;对vue应用中多个组件的共享状态进行集中式的管理&#xff08;读/写&#xff09;&#xff0c;也是一种组件间通信的方式&#xff0c;且适用于任意组件间通信。 2…

对抗样本攻击

对抗样本是指经过特殊设计或调整的输入数据&#xff0c;旨在欺骗人工智能模型&#xff0c;使其产生错误的预测或输出。对抗样本通常是通过对原始输入进行微小但精心计算的改变&#xff0c;使得模型产生意外的结果。这种模糊化的输入可能难以从人类角度甄别&#xff0c;但对机器…

顺序表的应用

文章目录 目录1. 基于动态顺序表实现通讯录项目2.顺序表经典算法2.1 [移除元素](https://leetcode.cn/problems/remove-element/description/)2.2 [合并两个有序数组](https://leetcode.cn/problems/merge-sorted-array/description/) 3. 顺序表的问题及思考 目录 基于动态顺序…

随机森林、AdaBoost 和 XGBoost 三者之间的主要区别

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 集成学习是一种强大的机器学习范式&#xff0c;它通过构建并结合多个学习器来提高预测性能。其中&#xff0c;随机森林、AdaBoost 和 XGBoost 是集成学习领域中著名且广泛应用的方法。尽管这些方法共享…

比selenium体验更好的ui自动化测试工具: cypress介绍

话说 Cypress is a next generation front end testing tool built for the modern web. And Cypress can test anything that runs in a browser.Cypress consists of a free, open source, locally installed Test Runner and a Dashboard Service for recording your tests.…

os.listdir()bug总结

今天测试出一个神奇的bug&#xff0c;算是教训吧&#xff0c;找了两天不知道问题在哪&#xff0c;最后才发现问题出现在这 原始文件夹显示 os.listdir()结果乱序 import os base_path "./file/"files os.listdir(base_path)print(files)问题原因 解决办法(排序)

蓝桥杯第十四届C++A组(未完)

【规律题】平方差 题目描述 给定 L, R&#xff0c;问 L ≤ x ≤ R 中有多少个数 x 满足存在整数 y,z 使得 。 输入格式 输入一行包含两个整数 L, R&#xff0c;用一个空格分隔。 输出格式 输出一行包含一个整数满足题目给定条件的 x 的数量。 样例输入 1 5 样例输出 …

文件怎么做成二维码图片?怎么用手机扫描二维码下载文件?

文件如何生成二维码图片&#xff1f;随着互联网的不断发展&#xff0c;用二维码来传递内容已经成为一种很常用的方式&#xff0c;其他人可以通过手机扫描生成二维码的方式来查看或者下载文件内容&#xff0c;有效提升文件传输的效率和速度。 现在制作活码类型的二维码可以在图…

JVM基础:类的生命周期详解

JDK版本&#xff1a;jdk8 IDEA版本&#xff1a;IntelliJ IDEA 2022.1.3 文章目录 一. 生命周期概述二. 加载阶段(Loading)2.1 加载步骤2.2 查看内存中的对象 三. 连接阶段(Linking)3.1 连接之验证3.2 连接之准备3.3 连接阶段之解析 四. 初始化阶段(Initialization)4.1 单个类的…

官方竞价排名是否对SEO自然排名有影响?

很多站长有疑问&#xff0c;如果使用搜索引擎官方的SEM竞价&#xff0c;是否对之前做的SEO自然优化排名有影响。这个问题我自己也有疑问。 因为很多站长认为是起绝对反作用&#xff0c;什么只要用了竞价&#xff0c;停止之后&#xff0c;原本很好的排名都会掉光。我们不否定一…

idea开发 java web 酒店推荐系统bootstrap框架开发协同过滤算法web结构java编程计算机网页

一、源码特点 java 酒店推荐推荐系统是一套完善的完整信息系统&#xff0c;结合java web开发和bootstrap UI框架完成本系统 采用协同过滤算法进行推荐 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式…

JAVA8 新特性StreamAPI使用(二)

一、使用StreamAPI&#xff0c;&#xff08;基于数据模型——客户、订单和商品&#xff0c;实体关系图如下&#xff0c;客户可以有多个订单&#xff0c;是一对多的关系&#xff0c;而产品和订单的关系是多对多的&#xff09;需求如下&#xff1a; 二、Stream API思维导图 三、需…