线程数

Java并发编程:线程池的使用

左心房为你撑大大i 提交于 2019-12-02 18:36:19
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:   如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。   那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?   在Java中可以通过线程池来达到这样的效果。今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPoolExecutor类中的方法讲起,然后再讲述它的实现原理,接着给出了它的使用示例,最后讨论了一下如何合理配置线程池的大小。   以下是本文的目录大纲:   一.Java中的ThreadPoolExecutor类   二.深入剖析线程池实现原理   三.使用示例   四.如何合理配置线程池的大小    若有不正之处请多多谅解,并欢迎批评指正。   请尊重作者劳动成果,转载请标明原文链接:   http://www.cnblogs.com/dolphin0520/p/3932921.html   一.Java中的ThreadPoolExecutor类   java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类

Java线程池的正确创建方式

不羁的心 提交于 2019-12-02 18:34:05
ThreadPoolExecutor分析 源码简单分析 参数说明 corePoolSize:核心线程数; maximumPoolSize:最大线程数,即线程池中允许存在的最大线程数; keepAliveTime:线程存活时间,对于超过核心线程数的线程,当线程处理空闲状态下,且维持时间达到keepAliveTime时,线程将被销毁; unit:keepAliveTime的时间单位 workQueue:工作队列,用于存在待执行的线程任务; threadFactory:创建线程的工厂,用于标记区分不同线程池所创建出来的线程; handler:当到达线程数上限或工作队列已满时的拒绝处理逻辑; 具体实现 1. 自定义队列 BlockingQueue < Runnable > q = new LinkedBlockingQueue < > ( 2048 ) ; BlockingQueue < Runnable > q = new ArrayBlockingQueue < > ( 10 ) ; LinkedBlockingQueue是一个阻塞队列,内部由两个ReentrantLock来实现出入队列的线程安全,由各自的Condition对象的await和signal来实现等待和唤醒功能。它和ArrayBlockingQueue的不同点在于: 队列大小有所不同

线程池ExecutorService空闲线程的个数

孤人 提交于 2019-12-02 18:33:31
keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0; allowCoreThreadTimeOut默认是false,即核心线程不会超时关闭,除非手动关闭线程池才会销毁线程 import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Main { public static void main(String[]

线程池用过吗?都有什么参数?底层如何实现的??

我只是一个虾纸丫 提交于 2019-12-02 18:24:15
corePoolSize:核心池的大小,这个参数跟后面讲述的线程池的实现原理有非常大的关系。在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务, 除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程。 默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; maximumPoolSize:线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程;如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize; 当阻塞队列是无界队列, 则maximumPoolSize则不起作用, 因为无法提交至核心线程池的线程会一直持续地放入workQueue. keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用

线程池参数的意义

江枫思渺然 提交于 2019-12-02 18:21:45
2019独角兽企业重金招聘Python工程师标准>>> 参考链接: https://www.cnblogs.com/jiangxiulian/p/7443983.html 1. corePoolSize: 核心线程数 缺省值为1 核心线程会一直存活,即使没有任务需要执行 当线程数小于核心线程数,即使有空闲线程,线程池也会优先创建新线程处理 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭 2. queueCapacity: 任务队列容量(阻塞队列) 当核心线程数达到最大时,新任务会放在队列中排队等待执行 3. maxPoolSize: 最大线程数 当前线程数 >= corePoolSize, 且任务对列已满时,线程池会创建新线程来处理任务 当前线程数 = maxPoolSize, 且任务对列已满时, 线程池会拒绝处理任务而抛出异常 4. keepAliveTime: 线程空闲时间 当空闲时间达到keepAliveTime时,线程会退出,直到线程数量等于corePoolSize 如果allowCoreThreadTimeout=true, 则线程会退出,直到线程数量等于0 5. allowCoreThreadTimeout:允许核心线程超时 缺省是false 6. rejectedExecutionHandler: 任务拒绝处理器

线程池各个参数详解以及如何自定义线程池

試著忘記壹切 提交于 2019-12-02 18:19:58
一:为什么要自己定义线程池 虽然jdk提供了几种常用特性的线程池给我们,但是很多时候,我还是需要自己去自定义自己需要特征的线程池。并且阿里巴巴规范手册里面,就是不建议使用jdk的线程池,而是建议程序员手动创建线程池。 为什么呢?原文如下 【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式, 这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险 说明:Executors 返回的线程池对象的弊端如下: 1、FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。 2、CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM 但是除此之外,自己通过ThreadPoolExecutor定义线程池还有很多好处。 比如说, 1.自己根据需求定义自己的拒绝策略,如果线程过多,任务过多 如何处理。 2.补充完善的线程信息,比如线程名,这一点在将来如果出现线上bug的时候,你会感谢自己,因为你绝不想在线上看到什么threa-1 threa-2 等这种线程爆出的错误,而且是看到自己 “处理xxx线程

Java 线程池全面解析

故事扮演 提交于 2019-12-02 18:19:17
转载自 https://mp.weixin.qq.com/s/fFZfEe10bdVKBndrEFH4fA 1. 什么是线程池? 很简单,简单看名字就知道是装有线程的池子,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程的复用。 2. 线程池的好处 我们知道不用线程池的话,每个线程都要通过new Thread(xxRunnable).start()的方式来创建并运行一个线程,线程少的话这不会是问题,而真实环境可能会开启多个线程让系统和程序达到最佳效率,当线程数达到一定数量就会耗尽系统的CPU和内存资源,也会造成GC频繁收集和停顿,因为每次创建和销毁一个线程都是要消耗系统资源的,如果为每个任务都创建线程这无疑是一个很大的性能瓶颈。所以,线程池中的线程复用极大节省了系统资源,当线程一段时间不再有任务处理时它也会自动销毁,而不会长驻内存。 3. 线程池核心类 在java.util.concurrent包中我们能找到线程池的定义,其中ThreadPoolExecutor是我们线程池核心类,首先看看线程池类的主要参数有哪些。 /** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory

java 线程池

给你一囗甜甜゛ 提交于 2019-12-02 18:13:45
Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的。在jdk1.5之后这一情况有了很大的改观。Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用。为我们在开发中处理线程的问题提供了非常大的帮助。 二:线程池 线程池的作用: 线程池作用就是限制系统中执行线程的数量。 根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。 为什么要用线程池: 1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。 2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。 Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具

如何优雅的设置线程池的大小?

被刻印的时光 ゝ 提交于 2019-12-02 18:09:52
线程池需要设置合适的大小,假如设置的太大,线程上线文切换过于频繁,造成大量资源开销,反而会使性能降低。假如设置的太小,存在很多可用的处理器资源却未在工作,会造成资源的浪费和对吞吐量造成损失。 为了充分利用处理器资源,创建的线程数至少要等于处理器核心数。如果所有的任务都是计算密集型的,那么线程数等于可用的处理器核心数就可以了。不过,如果所有的任务都是IO密集型,那么处理器大部分时间是空闲的,所有要适当的增加线程数。 线程等待时间所占比例越高,需要越多线程。线程运算时间所占比例越高,需要越少线程。 于是可以使用下面的公式进行估算: 最佳线程数 = (1 + 线程等待时间/线程计算时间)* 目标CPU的使用率 * 处理器核心数 例如:平均每个线程计算运行时间为0.5s,而线程等待时间(非计算时间,比如IO)为1.5s,目标CPU的使用率是90%,CPU核心数为8,那么根据上面这个公式估算得到:(1 + 1.5/0.5) * 90% * 8 = 28.8。 即使有上面的简单估算方法,也许看似合理,但实际上也未必合理,都需要结合系统真实情况(比如是IO密集型或者是CPU密集型或者是纯内存操作)和硬件环境(CPU、内存、硬盘读写速度、网络状况等)来不断尝试达到一个符合实际的合理估算值,也可以尝试 Dark Magic的估算方法 。 来源: https://www.cnblogs.com

Java线程池的正确打开方式

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-02 18:03:38
当前环境 jdk == 1.8 Executors 使用的隐患 先来看一段代码,我们要创建一个固定线程池,假设固定线程数是4。代码如下: Executors 是JAVA并发包中提供的,用来快速创建不同类型的线程池。 是不是很简单,创建线程池只需一行代码。对于一些个人项目或临时性的项目,这样写确实没什么问题,而且开发速度很快。但在一些大型项目中,这种做法一般是禁止的。 WHY??? 因为用 Executors 创建的线程池存在性能隐患,我们看一下源码就知道,用 Executors 创建线程池时,使用的队列是 new LinkedBlockingQueue<Runnable>() ,这是一个无边界队列,如果不断的往里加任务时,最终会导致内存问题,也就是说在项目中由于使用了无边界队列,导致的内存占用的不可控性。下图是不断添加线程任务导致老年代被占满的情况: 当然,除了内存问题,它还存在一些其他的问题,在下面对线程池参数的介绍中会具体说明。 线程池的正确创建方式 其实,问题很好解决。提供的简便方式有局限性,那我们自己new一个 ThreadPoolExecutor ,无非多写几行代码而已。 关于 ThreadPoolExecutor 的具体代码如下: 参数说明: corePoolSize:核心线程数; maximumPoolSize:最大线程数,即线程池中允许存在的最大线程数;