concurrent并发包里面几个重要的接口有:Executor、ExecutorService, ScheduledExecutorService
;
重要的实现类有:ScheduledThreadPoolExecutor, ThreadPoolExecutor
;
关于这几个接口和实现类的类图可以参见文档最后的UML图,图中对一些比较重要的属性、方法进行红色标识,可以重点关注;
先来说说java.util.concurrent.ThreadPoolExecutor
,也就是我们经常说到的线程池,通过该类,应用可以直接拿来使用,只要在初始化时设置不同的参数即可;其主要的参数有以下几个:
-
corePoolSize
: 线程池维护线程的最少数量
-
maximumPoolSize
:线程池维护线程的最大数量
-
keepAliveTime
: 线程池维护线程所允许的空闲时间
-
unit
: 线程池维护线程所允许的空闲时间的单位
-
workQueue
: 线程池所使用的缓冲队列
-
handler
: 线程池对拒绝任务的处理策略
一个任务通过execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是Runnable类型对象的run()方法;注意:是Runnable,而不是Thread
。
当一个任务通过execute(Runnable)方法欲添加到线程池时:
- 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
- 如果此时线程池中的数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列。
- 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
- 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过handler所指定的策略来处理此任务。
- 从上面可以看出线程池中处理任务的优先级为:
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。
默认handler有四个选择,当然也可以自行扩展,但是要特别小心:
- ThreadPoolExecutor.AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常;
- ThreadPoolExecutor.CallerRunsPolicy:主线程直接尝试执行该任务;当线程池中可加入时,将任务添加到线程池中;该操作会重复执行,可以有效降低主线程将任务加入到线程池的速度;
- ThreadPoolExecutor.DiscardOldestPolicy:直接抛弃旧的任务,即把线程池内最早加入队列的线程抛弃;
- ThreadPoolExecutor.DiscardPolicy:直接抛弃当前的任务;
再来说说java.util.concurrent.ScheduledThreadPoolExecutor
,此类是ThreadPoolExecutor的子类,所以以上我们描述的特性他都具备;除此之外,他还有一些自己特有的属性和方法:
- schedule(Runnable command, long delay, TimeUnit unit)
该方法创建并执行在给定延迟后启用的一次性任务;
- scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
该方法创建并执行一个在给定初始延迟后首次启用的定期任务,后续任务具有指定的周期;也就是将在initialDelay后开始执行,然后在initialDelay+period 后执行,接着在initialDelay + 2 * period 后执行,依此类推。
- scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
该方法创建并执行一个在给定初始延迟后首次启用的定期任务,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。
对于concurrent包在Spring中也进行了很多的封装,对于一些可以采用FixedRate
或者FixedDelay
来进行调度的任务,非常的方便,相比较于Quartz的实现,在配置文件方面要减少很多,有兴趣的同学可以参考Spring文档中的《第23章 Spring中的定时调度和线程池》,重点关注两个类:
org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean
org.springframework.scheduling.concurrent.ScheduledExecutorTask
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
附:concurrent包中几个核心接口、类的UML类图:
知识容易遗忘,这里作为一个备份手册粘贴于此,感谢:http://www.alisdn.com/wordpress/?p=1133
分享到:
相关推荐
jdk中线程安全的集合类.docx
对java多线程进行了全面的总结,包括了JDK 5的新特性。
通过接口java.util.concurrent.Callable 的使用 实现线程的启用,程序为一个main的例子,可以直接运行(jdk1.5 以上版本)
JDK5中的多线程并发库.doc 描述了JDK多线程的并发
JDK7多线程部分类(接口)关系图,根据官网得出
JDK5中的多线程并发库
JDK 5.0 是用 Java 语言创建高可伸缩的并发应用程序的主要步骤。JVM 已经进行了改进,允许类利用硬件级别支持并发,并且提供了一组丰富的新并发构造块,使开发并发应用程序更加容易。 <br>本教程将介绍 JDK 5.0 ...
JDK21的虚拟线程,不需要操作系统的原生支持,可以在没有物理机的情况下运行,极大地降低了线程的创建和管理开销。 普通线程的实现方式 普通线程需要操作系统的原生支持,它的创建和管理都需要消耗一定的系统资源,...
最常用和实用的JDK内存和线程监控指令,堆栈监控指令及操作步骤
异步不用回填数据,返回页面则需要回填 Viso跨职能流程图可分析各个系统流转流程 ...当服务为对接方式的时候,判断是否有权限,有则按照数据封装传入,无权限则查询出来,再将数据放入对象模块中再传入
整理的一些资料,jdk1.5新增加对线程并发的处理类,可以学习一下
Java多线程--JDK5.0新增线程创建方式
JAVA线程总结,包含线程池,显示使用线程实现异步编程,基于JDK中的Future实现异步编程,JDK中的FutureTask等
1.1 JDK7新特性<一>概述 . . . . . . . . . . . . . . 1.2 JDK7新特性<二> 语法 . . . . . . . . . . . . . 1.3 JDK7新特性<三> JDBC4.1 . . . . . . . . . . 1.4 JDK7新特性<四> NIO2.0 文件系统 . . . 1.5 JDK...
由浅入深,通过图解和手写代码,讲解Java版的多线程,主要讲解如下内容: ...JDK多线程工具包中,若干种工具的原理和手写实现: ReentrantLock、CountDownLanuh、CyclicBarrier、Semaphore
介绍一个通用多线程服务模块。是利用jdk线程池,多线程并行处理多任务,以提高执行效率。
在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。
JDK和JVM以及线程储存方面
Java-jdk10-最新最全多线程编程实战指南-核心篇
本书的新版本展示了如何利用Java线程工具的全部优势,并介绍了JDK 2线程接口中的最新变化。你将学习如何使用线程来提高效率,如何有效地使用它们,以及如何避免常见的错误。本书讨论了死锁、竞态条件以及饥饿等问题...