当前位置:网站首页>并发编程——线程池
并发编程——线程池
2022-06-22 04:45:00 【v_BinWei_v】
并发编程——线程池
1、线程池介绍
创建一个线程非常简便,但是如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。为了解决这样的问题,Java提出了线程池这个解决方法.所谓的线程池其实就是一个存放线程的容器.调用线程池去执行并发任务时,从线程池中取出线程去执行任务,每个线程 执行完任务,并不被销毁,而是被线程池回收,下一次继续执行任务。
首先创建线程池有两种方式,第一种是使用Executors框架的工具类创建类各种类型的线程池,第二种是直接**new ThreadPoolExecutor()**的线程池,中间的各种参数自己定义,两种方法各有优劣。
2、创建线程池的方法
2.1、Executors框架创建线程池
EXecutors采用工厂模式创建四种类型的 ThreadPoolExecutor 线程池
- FixedThreadPool : 该方法返回一个固定线程数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。
- SingleThreadExecutor: 方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。
- CachedThreadPool: 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。
- ScheduledExecutorService 可以实现循环或延迟任务 在对延迟任务和循环任务要求严格的时候
具体创建方式
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
ExecutorService fixedFhreadPool = Executors.newFixedThreadPool();
Executors.newScheduledThreadPool();
源码分析
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AwCjFsRH-1655536900843)(F:\西电研究生\学长简历\项目经验总结.assets\image-20220506190204993.png)]](/img/24/cbf6a48bed91e98225d435d1d01012.png)
Executor
Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的.
ExecutorService
ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等方法。
exectue() 和 submit()的区别
1. **`execute()`方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;**
2. **`submit()`方法用于提交需要返回值的任务。线程池会返回一个 `Future` 类型的对象,通过这个 `Future` 对象可以判断任务是否执行成功**,并且可以通过 `Future` 的 `get()`方法来获取返回值,`get()`方法会阻塞当前线程直到任务完成,而使用 `get(long timeout,TimeUnit unit)`方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。
AbstractExecutorService
抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
ThreadPoolExecutor
ThreadPoolExecutor继承了类AbstractExecutorService。
2.2 直接使用ThreadPoolExecutor创建线程池
使用ThreadPoolExecutor主要是配置对应参数
/* Creates a new ThreadPoolExecutor with the given initial parameters. Params: corePoolSize – the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set maximumPoolSize – the maximum number of threads to allow in the pool keepAliveTime – when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating. unit – the time unit for the keepAliveTime argument workQueue – the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method. threadFactory – the factory to use when the executor creates a new thread handler – the handler to use when execution is blocked because the thread bounds and queue capacities are reached Throws: IllegalArgumentException – if one of the following holds: corePoolSize < 0 keepAliveTime < 0 maximumPoolSize <= 0 maximumPoolSize < corePoolSize NullPointerException – if workQueue or threadFactory or handler is null */
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
参数详解:
corePoolSize:表示在线程中一直保持的线程数,即使这些线程在空闲状态,也一直保持
maximumPoolSize:线程池中能拥有的最多线程数
keepAliveTime: 当线程数大于内核时,这是多余的空闲线程在终止之前等待新任务的最长时间。
unit: 时间单元,TimeUnit.SECONDS、TimeUnit.HOURS…
workQueue: 用于在执行任务之前保存任务的队列。此队列将仅保存由 execute 方法提交的可运行任务
threadFactory: 执行程序创建新线程时要使用的工厂
handler: 由于达到线程边界和队列容量而被阻止执行时要使用的处理程序
RejectedExecutionHandler 拒绝策略:
AbortPolicy:该策略是线程池的默认策略。使用该策略时,如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException异常。
DiscardPolicy:这个策略和AbortPolicy的slient版本,如果线程池队列满了,会直接丢掉这个任务并且不会有任何异常。
DiscardOldestPolicy:这个策略从字面上也很好理解,丢弃最老的。也就是说如果队列满了,会将最早进入队列的任务删掉腾出空间,再尝试加入队列。因为队列是队尾进,队头出,所以队头元素是最老的,因此每次都是移除对头元素后再尝试入队。
CallerRunsPolicy:使用此策略,如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行。就像是个急脾气的人,我等不到别人来做这件事就干脆自己干。
自定义:自定义拒绝内容和方法
测试拒绝策略代码
class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
try {
System.out.println(this.name + " is running.");
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.HOURS, new ArrayBlockingQueue<Runnable>(1));
// 设置线程池的拒绝策略为"丢弃"
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// 新建10个任务,并将它们添加到线程池中。
for (int i = 0; i < 10; i++) {
Runnable myrun = new MyRunnable("task-"+i);
pool.submit(myrun);
}
// 关闭线程池
pool.shutdown();
输出结果
3、并发编程的开发规则
1、获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
2、创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
3、线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
4、线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。因此推荐使用第二种创建线程的方法
说明:Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
边栏推荐
- Web page design and production final assignment report - College Students' online flower shop
- 【使用指南】清华源的使用
- Why does golang not recommend this/self/me/that/_ this
- POSIX semaphore
- Web design and production final assignment report -- animator Hayao Miyazaki
- How to deal with too small picture downloaded from xuexin.com
- 下拉刷新,上推加载(简单好用,终于会了)
- 【科研笔记】Focal Loss
- [learn FPGA programming from scratch -39]: Advanced - syntax - unit test of hardware module: simulation excitation, testbench
- Es cannot work, circuitbreakingexception
猜你喜欢

Web design and production final assignment report - minority music website

获取DPI函数返回值永远是96 | 获取DPI函数返回值不正确 | GetDpiForMonitor/GetDeviceCaps返回值不正确的原因

轻量级CNN设计技巧

Get the specified row content in Oracle rownum and row_ number()

Redis 主从复制

Leetcode -- the kth largest node of the binary search tree (traversal by means of middle order)

【故障诊断】stitch.py脚本失效

Online document collaboration: a necessary efficient artifact for office

slurm 使用教程

《数据库原理》期末考试题
随机推荐
Reasons and Countermeasures for ThinkPHP's session being unable to obtain session in different ways in the same controller
爬梯子&&卖卖股份的最佳时期(跑路人笔记)
当程序员编程时被打扰 | 每日趣闻
Great! Huaibei and Huaibei enterprises are approved to use special marks for geographical indication products
【故障诊断】切图代码切不出来,slide.read_region不运行,但程序不报错
MySQL notes
Get the specified row content in Oracle rownum and row_ number()
Zhongmin online: sharing online channel resources with "points" as the link
Recruiters - issue 23
Go learning notes
[sdx62] IPA log fetching instructions
Slurm tutorial
C # WinForm listview control has no scroll bar and has written an extension control by itself
Digital economy Wang Ning teaches you how to correctly choose short-term investment
ORA-15063: ASM discovered an insufficient number of disks for diskgroup 恢复---惜分飞
Ora-15063: ASM discovered an insufficient number of disks for diskgroup
On the income of enterprise executives
Specific concept of interceptor
Code example of map and entity class Interoperation
How SQL server generates change scripts