当前位置:网站首页>黑马程序员线程池
黑马程序员线程池
2022-07-19 05:16:00 【闲易生事】
什么是线程池
线程池就是一个可以复用线程的技术。、
不使用线程池的问题
如果用户每发起一个请求,后台就创建一个新线程来处理,下次任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。
谁代表线程池?
JDK5.0起提供了代表线程池的接口:ExecutorService
如何得到线程池对象
方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。
ExecutorService |
ThreadPoolExecutor |
方式二:使用Executors(线程池工具类)调用方法返回不同特点的线程池对象。
ThreadPoolExecutor构造器参数说明
参数一 | 指定线程池线程数量(核心线程) | corePoolSize | 不能小于0 |
参数二 | 指定线程可支持的最大线程数 | maximumPoolSize | 最大数量>=核心线程数量 |
参数三 | 指定临时线程的最大存活时间 | keepAliveTime | 不能小于0 |
参数四 | 指定存活时间的单位(秒分时天) | unit | 时间单位 |
参数五 | 指定任务队列 | workQueue | 不能为null |
参数六 | 指定用哪个线程工厂创建线程 | threadFactory | 不能为null |
参数七 | 指定线程忙,任务满的时候,新任务来了怎么办 | handler | 不能为null |
线程池常见面试题
临时线程什么时候创建?
新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程
什么时候会开始拒绝任务?
核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。
线程池处理Runnable任务
ExecutorService pool = new ThreadPoolExecutor(3,5,8,TimeUnit.SECONDS,new ArrayBlockingQueue<>(6),Executors.defaultThreadFactory(),new ThreaddPoolExecutor.AbortPolicy());
方法名称 | 说明 |
void execute(Runnable command) | 执行任务/命令,没有返回值,一般用来执行Runnable任务 |
Future<T> submit(Callable<T> task) | 执行任务,返回未来任务对象获取线程结果,一般拿来执行Callable任务 |
void shutdow() | 等任务执行完毕后关闭线程池 |
List<Runnabke> shutdownNow() | 立刻关闭,停止正在执行的任务,并返回队列中未执行的任务 |
代码实现
import java.util.concurrent.*;
/*
* 目标:自定义一个线程池对象,并测试其特性。
* */
public class ThreadPoolDemo1 {
public static void main(String[] args) {
// 1,创建线程池对象
ExecutorService pool =new ThreadPoolExecutor(3,5,6,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
// 给任务让线程池处理
Runnable target=new MyRunnable();//这不是线程,而是任务对象
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
//当任务不超过8(3个核心线程+5个任务队列)个 不会创建临时线程。
//此线程池最多可以同时执行10(8+2个临时线程)个任务
}
}
—————————————————————————————————————————————————————————————————————————————————————————
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName()+"输出了:离谱"+i);
}
}
}
新任务拒绝策略
策略 | 详解 |
ThreadPoolExecutor.AbortPolicy | 丢弃任务并抛出RejectedExecutionException异常。这是默认的策略 |
ThreadPoolExecutor.DiscardPolicy | 丢弃任务,但不抛出异常。这是不推荐的做法 |
ThreadPoolExecutor.DiscardOldestPolicy | 抛弃队列中等待最长的任务 然后把当前任务加入队列中 |
ThreadPoolExecutor.CallerRunsPolicy | 由主线程负责调用任务的run()方法从而绕过线程池直接执行 |
线程池处理Callable任务
import java.util.concurrent.*;
public class ThreadPoolDemo2 {
public static void main(String[] args)throws Exception {
// 1,创建线程池对象
ExecutorService pool =new ThreadPoolExecutor(3,5,6,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
// 给任务让线程池处理
Callable<String> callable=new MyCallable(100);
Future<String>f1= pool.submit(callable);
Future<String>f2= pool.submit(callable);
Future<String>f3= pool.submit(callable);
Future<String>f4= pool.submit(callable);
Future<String>f5= pool.submit(callable);
Future<String>f6= pool.submit(callable);
System.out.println(f1.get());
System.out.println(f2.get());
System.out.println(f3.get());
System.out.println(f4.get());
System.out.println(f5.get());
System.out.println(f6.get());
}
}
—————————————————————————————————————————————————————————————————————————————————————————
import java.util.concurrent.Callable;
public class MyCallable implements Callable<String> {
private int n ;
public MyCallable(int n){
this.n=n;
}
@Override
public String call() throws Exception {
int sum=0;
for (int i = 0; i <= n; i++) {
sum += i;
}
return Thread.currentThread().getName()+"执行结果是:"+sum;
}
}
Executors得到线程池对象的常用方法
Executors:线程池工具类通过调用方法返回不同类型的线程池对象。
方法名称 | 说明 |
public static ExecutorService newCachedThreadPool() | 线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了一段时间则会被回收掉。 |
public static ExecutorService newFixedThreadPool(int nThreads) | 创建固定线程数量的线程池,入过某个线程因为执行异常而结束,那么线程池会补充一个新的线程替代它。 |
public static ExecutorService newSingleThreadExecutor() | 创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新的线程 |
public static ScheduleExecutorService newScheduledThreadPool(int corePoolSize) | 创建一个线程池,可以实现在给定的延迟后运行任务,或者定期执行任务。 |
注意:Executors的底层也是基于线程池的实现类ThreadPoolExecutor创建的线程池对象。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* 目标:使用Executors的工具方法直接得到一个线程池对象
* */
public class ThreadPoolDemo3 {
public static void main(String[] args) {
ExecutorService pool= Executors.newFixedThreadPool(3);
Runnable runnable=new MyRunnable();
pool.execute(runnable);
pool.execute(runnable);
pool.execute(runnable);
pool.execute(runnable);
}
}
Executors使用可能会存在陷阱
大型并发系统环境中使用Executors如果不注意可能会出现系统风险(OOM)。
边栏推荐
- Leetcode:2. Add two numbers [large number addition + analog carry]
- Network Security Learning (XXII) build virtual special lines for companies and branches
- Servlet概述
- Computer 408+ database [suitable for postgraduate entrance examination or final review]
- Unreal Engine learning (2)
- 网络安全学习(二十三)防火墙
- 我的2020年线上的夏令营总结
- equals和“==”的异同
- How to set the oil on the through hole cover when exporting the Gerber file of PCB
- Leshan normal programming competition 2020-h: least common multiple [find the number of factors]
猜你喜欢
FPGA skimming P4: use 8-3 priority encoder to realize 16-4 priority encoder, use 3-8 decoder to realize full subtracter, realize 3-8 decoder, use 3-8 decoder to realize logic function, and use data se
Network Security Learning (XX) ACL
RDO deployment openstack single node
ESM测向误差对定位误差的影响分析
网安学习(二十)ACL
Software engineering final review mind map
第二次实验 静态路由的扩展配置
雷达基础知识
2022-7-18 guyujia's study notes of group 8
网络安全学习(十五)ARP
随机推荐
2022-7-11 第八小组 顾宇佳 学习笔记(Js)
Network Security Learning (XVII) VLAN
网络安全与等级保护
equals和“==”的异同
经纬度及其与坐标系的转换
Panzer_Jack 的 个人博客成立日
Leetcode:2. 两数相加【大数加法+模拟进位】
乐山师范程序设计大赛2020-F: 我的魔法【模拟】
2022-7-15 Gu Yujia's study notes of the eighth group
乐山师范程序设计大赛2020-C: 最大乘积【思维】
Experience of installing ROS in Jetson nano (failed)
字符串常见方法总结:
关于在终端下使用npm命令,安装错误问题解决(自身经历)
[2022/7/17]科研整理
方向信号的表达——复指数信号
浅谈Excel文件解析
上海二工大 - 健康日报AutoCheck
乐山师范程序设计大赛2020-G: 最大公约数【思维】
网络安全学习(十四)IP协议
IP---ia复习