展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

Executor框架

  • 案例1
public class ExecutorDemo {
public static void main(String[] args) {
// 方式1
ExecutorService executorService = Executors.newCachedThreadPool();
// 方式2,传入参数,线程数量
ExecutorService executorService1 = Executors.newFixedThreadPool(2);
// 方式3,传入参数,核心线程数量
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// 方式4
ExecutorService executorService2 = Executors.newWorkStealingPool();
// 方式5
ExecutorService executorService3 = Executors.newSingleThreadExecutor();
// 方式6
ScheduledExecutorService scheduledExecutorService1 = Executors.newSingleThreadScheduledExecutor();
// 使用方式都是,提交任务到线程池
executorService.submit(() -> {
System.out.println(Thread.currentThread().getName());
});
}
}
  • 简介
newCachedThreadPool:创建一个可以根据需要创建新线程的线程池,如果有空闲线程,优先使用空闲的线程
# 查看源码
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, // 核心线程数、最大线程容量
60L, TimeUnit.SECONDS, // 存活时间60毫秒
new SynchronousQueue<Runnable>()); // 工作队列
}
newFixedThreadPool:创建一个固定大小的线程池,在任何时候,最多只有N个线程在处理任务
newScheduledThreadPool:能延迟执行、定时执行的线程池
newWorkStealingPool:工作窃取,使用多个队列来减少竞争
newSingleThreadExecutor:单一线程的线程池,只会使用唯一一个线程来执行任务,即使提交再多的任务,也都是会放到等待队列里进行等待 newSingleThreadScheduledExecutor:单线程能延迟执行、定时执行的线程池
  • 线程池的使用建议
尽量避免使用Executor框架创建线程池
newFixedThreadPool newSingleThreadExecutor 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM
newCachedThreadPool newScheduledThreadPool 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM
  • 案例2: 模拟OOM异常
public class OOMDemo {
public static void main(String[] args) {
// new 1个线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 死循环向线程池中提交任务
while (true) {
executorService.submit(() -> {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
  • 设置VM options



-Xms60m
-Xmx60m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=C:\work
  • 执行结果
# C:\work路径下生成文件
pool-1-thread-1
pool-1-thread-2
java.lang.OutOfMemoryError: Java heap space
Dumping heap to C:\work\java_pid7132.hprof ...
Heap dump file created [113116988 bytes in 0.993 secs]
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "pool-1-thread-1"
Process finished with exit code 1
  • 运行ha456.jar
java -jar ha456.jar

  • 案例3: 模拟OOM异常
# 在限定了堆的内存之后,还会把整个电脑的内存撑爆
# 创建线程时用的内存并不是我们制定jvm堆内存,而是系统的剩余内存
public class OOMDemo2 {
public static void main(String[] args) {
// new 1个线程池
ExecutorService executorService = Executors.newCachedThreadPool();
while (true) {
executorService.submit(() -> { // 不断提交任务到线程池
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
  • 线程池使用建议
创建线程池时,核心线程数不要过大
相应的逻辑,发生异常时要处理
submit 如果发生异常,不会立即抛出,而是在get的时候,再抛出异常
execute 直接抛出异常
  • 案例4
public class OOMDemo3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
for (int i = 0; i < 100; i++) {
Future<Integer> submit = executorService.submit(() -> { // 提交任务到线程池
System.out.println(Thread.currentThread().getName());
return 1 / 0;
});
submit.get();
}
}
}
# 控制台打印结果
pool-1-thread-1
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at com.xdclass.pool.OOMDemo3.main(OOMDemo3.java:22)
Caused by: java.lang.ArithmeticException: / by zero
at com.xdclass.pool.OOMDemo3.lambda$main$0(OOMDemo3.java:19)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
  • 案例5
public class OOMDemo3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
for (int i = 0; i < 100; i++) {
executorService.execute(() -> { // 提交任务到线程池
System.out.println(Thread.currentThread().getName());
int j=1/0;
});
}
}
}
# 控制台打印结果
pool-1-thread-24
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at com.xdclass.pool.OOMDemo3.lambda$main$0(OOMDemo3.java:19)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Exception in thread "pool-1-thread-3" Exception in thread "pool-1-thread-2" java.lang.ArithmeticException: / by zero
posted @   DogLeftover  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
历史上的今天:
2021-05-16 真实机中安装CentOS7(一)
点击右上角即可分享
微信分享提示