当前位置: 首页 > news >正文

创建线程池时为什么不建议使用Executors进行创建

有没有想过为什么在创建线程池的时候我们一般都是通过ThreadPoolExecutor来创建线程池,很少使用Executors来创建线程池?

实践出真知,让我们具体在代码里面看看是什么原因~
我们先用Executors来创建一个固定线程的线程池:

    @Testpublic void test2(){ExecutorService executorService1 = Executors.newFixedThreadPool(10);for(int i=0;i<Integer.MAX_VALUE;i++){executorService1.execute(new MyThread1());}}
}class MyThread1 implements Runnable{@Overridepublic void run() {try {Thread.sleep(10);}catch (Exception e){e.printStackTrace();}}
}

通过指定JVM参数:-Xmx8m -Xms8m 运行以上代码,会抛出OOM:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceededat java.util.concurrent.LinkedBlockingQueue.offer(LinkedBlockingQueue.java:416)at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)

其实这里提示的就很明显的,主要是因为LinkedBlockingQueue出了问题,我们再来看一下底层:

Java中的BlockingQueue主要有两种实现,分别是ArrayBlockingQueueLinkedBlockingQueue

ArrayBlockingQueue 是有边界阻塞队列,对于LinkedBlockingQueue 来说如果没有指定大小的话将是一个无边界阻塞队列,而且里面的最大值如果在没有指定大小的情况下可以达到Integer.MAX_VALUE,对于一个无边界队列来说,是可以不断的向队列中加入任务的,所以这个时候就会出现内存溢出的问题。

上面提到的问题主要体现在newFixedThreadPoolnewSingleThreadExecutor两个工厂方法上,并不是说newCachedThreadPoolnewScheduledThreadPool这两个方法就安全了,这两种方式创建的最大线程数可能是Integer.MAX_VALUE,而创建这么多线程,必然就有可能导致OOM。

阿里巴巴java开发手册上也明确说了尽量不用Executors创建线程池:

那既然问题找到了,我们解决问题就行啦~即对BlockingQueue设置初始值就行,这样一个无边界的阻塞队列就可以变成有边界的阻塞队列

 @Testpublic void test2(){ExecutorService executorService1 = new ThreadPoolExecutor(10,30,100,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),new ThreadPoolExecutor.CallerRunsPolicy();for(int i=0;i<Integer.MAX_VALUE;i++){executorService1.execute(new MyThread1());}}
}class MyThread1 implements Runnable{@Overridepublic void run() {try {Thread.sleep(10);}catch (Exception e){e.printStackTrace();}}
}

这种情况下,一旦线程提交数超过我设定的数值,就会报一个异常`java.util.concurrent.RejectedExecutionException,这是因为当前队列已经是一个有边界的阻塞队列,一旦请求数量超过我设定的数值,就会抛出一个异常。

除了自己定义`ThreadPoolExecutor`外。还有其他方法。这个时候第一时间就应该想到开源类库,如apache和guava等。这里作者就不展开描述啦~感兴趣的小伙伴可以自己翻阅资料学习哦~


http://www.mrgr.cn/news/63332.html

相关文章:

  • Flutter-Engine 的定制实践:Text 绘制流程浅析及自定义underline的间距
  • conda的对应环境下安装cuda11.0和对应的cudnn
  • flask websocket服务搭建,flask-sock 和 flask-socketio
  • Harmony OS搭建广告展示页
  • Centos安装配置Jenkins
  • SpringBoot 将多个Excel打包下载
  • VMware Workstation 17.0虚拟机安装Ubuntu Server 22.04.5 LTS并配置SSH与XFTP详细过程
  • 基于Matlab GUI的说话人识别测试平台
  • 基于SpringBoot的健身房系统的设计与实现(源码+定制+开发)
  • 国标GB28181摄像机接入EasyGBS国标GB28181软件与国标协议对接解决方案
  • 聚“芯”而行,华普微亮相第五届Silicon Labs Works With大会
  • HashSet 和 TreeSet 分别是如何实现去重的
  • Java 批量导出Word模板生成ZIP文件到浏览器默认下载位置
  • 【经验分享】从网页下载内嵌PDF的小妙招,亲测好用
  • OpenEuler 使用ffmpeg x11grab捕获屏幕流,rtsp推流,并用vlc播放
  • React04 State变量 组件渲染
  • fasdsdsadsa
  • 2024高性价比电容笔推荐!盘点实测西圣、绿联、酷盟电容笔!
  • qt QStackedWidget详解
  • Gemini API 和 Google AI Studio 升级,提升搜索准确性和响应能力
  • L 波段射频信号采集回放系统
  • window与Linux基础-1
  • Jenkins You‘re using ‘Known hosts file‘,known_hosts file does not exist
  • QList
  • 图片批量处理神器将每个文件夹中的多张图片拼接,一键实现横向和纵向的长图拼接效果,让你的图片处理更高效
  • 漓江景区景点推荐