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

织梦模板添加网站地图IT科技资讯新闻类织梦网站模板

织梦模板添加网站地图,IT科技资讯新闻类织梦网站模板,辽阳化工网站建设,重庆电商平台网站建设先说结论: 假如有20CompletableFuture任务并发执行时,都使用默认线程池ForkJoinPool,但cpu的核心数又小于3,那么就会新建20个线程(不使用默认线程池了),这20个线程相互竞争cpu资源和内存&#x…

先说结论:
假如有20CompletableFuture任务并发执行时,都使用默认线程池ForkJoinPool,但cpu的核心数又小于3,那么就会新建20个线程(不使用默认线程池了),这20个线程相互竞争cpu资源和内存,很多线程都在等待,浪费了大量的性能在线程上下文切换上。

线程池大小设定:

  • 如果服务是cpu密集型的,设置为电脑的核数
  • 如果服务是io密集型的,设置为电脑的核数*2

runAsync方法点进去

    CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {System.out.println(1);});

可以看见使用的是asyncPool。点进asyncPool

    public static CompletableFuture<Void> runAsync(Runnable runnable) {return asyncRunStage(asyncPool, runnable);}

useCommonPool是否为true决定了使用 ForkJoinPool线程池还是新建一个线程池。点进useCommonPool。

    private static final Executor asyncPool = useCommonPool ?ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();

这里判定的是ForkJoinPool common线程池中并行度级别是否大于1。点进 getCommonPoolParallelism() 方法

    private static final boolean useCommonPool =(ForkJoinPool.getCommonPoolParallelism() > 1);

返回的是commonParallelism这个字段,再往下找。

    public static int getCommonPoolParallelism() {return commonParallelism;}

发现只有一个地方对这个属性进行赋值,继续。

    static final int commonParallelism;

在这里插入图片描述

发现commonParallelism 由par决定,par来自common.config SMASK做与运算。SMASK定义为0xffff(65535),common.config由 makeCommonPool()得到。点进makeCommonPool()方法

...
static final ForkJoinPool common;
static {...common = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<ForkJoinPool>() {public ForkJoinPool run() {return makeCommonPool(); //common的config由此方法返回}});int par = common.config & SMASK; // report 1 even if threads disabledcommonParallelism = par > 0 ? par : 1;
}

在这里插入图片描述

我简化了下面源码,parallelism 初始化为 -1,若jvm启动参数有java.util.concurrent.ForkJoinPool.common那么parallelism将会被启动参数指定。Runtime.getRuntime().availableProcessors() 是获取虚拟机可使用的处理器数量。在jvm未定义参数的前提下,处理器数量若小于等于2,那么并行度parallelism就为1,反之则为 (处理器数量 - 1)。定义了jvm参数,若参数值大于MAX_CAP(32767),则重新赋值。即parallelism 总会大于0, 继续点进ForkJoinPool的构造方法。

    private static ForkJoinPool makeCommonPool() {...int parallelism = -1;try {  // ignore exceptions in accessing/parsing propertiesString pp = System.getProperty("java.util.concurrent.ForkJoinPool.common.parallelism");if (pp != null)parallelism = Integer.parseInt(pp);} catch (Exception ignore) {}if (parallelism < 0 && // default 1 less than #cores(parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)parallelism = 1;if (parallelism > MAX_CAP)parallelism = MAX_CAP;return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE, // 注意 LIFO_QUEUE等于0 "ForkJoinPool.commonPool-worker-");}

发现config也是作位运算,即config也会大于0,我们拿到这个config返回开始 par 赋值那一块。

    private ForkJoinPool(int parallelism,ForkJoinWorkerThreadFactory factory,UncaughtExceptionHandler handler,int mode,String workerNamePrefix) {this.workerNamePrefix = workerNamePrefix;this.factory = factory;this.ueh = handler;this.config = (parallelism & SMASK) | mode; // SMASK等于65535,mode等于0long np = (long)(-parallelism); // offset ctl countsthis.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);}

总结就是并行度 parallelism(大于0) 与 65535(111111…) 做两次与运算,即本身。继续回到之前

...
static final ForkJoinPool common;
static {...common = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<ForkJoinPool>() {public ForkJoinPool run() {return makeCommonPool(); //common的config由此方法返回}});int par = common.config & SMASK; // report 1 even if threads disabledcommonParallelism = par > 0 ? par : 1;
}

这里判断,

  • 无JVM参数前提下:
    • 若服务器的核心数小于等于2,commonParallelism 则为1,即useCommonPool 为false,new 一个线程池。
    • 若服务器的核心数大于2,commonParallelism 则为 核心数 - 1,即useCommonPool 为true,使用ForkJoinPool线程池。
  • 有JVM参数,以设置参数为准。大于1小于等于32767。和上面判断一致。
    private static final Executor asyncPool = useCommonPool ?ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();private static final boolean useCommonPool =(ForkJoinPool.getCommonPoolParallelism() > 1);public static int getCommonPoolParallelism() {return commonParallelism;}

在ThreadPerTaskExecutor 中 execute,他会为每个任务新开一个线程,而不是采用ForkJoinPool中的线程。

    static final class ThreadPerTaskExecutor implements Executor {public void execute(Runnable r) { new Thread(r).start(); }}

结论:jvm启动参数中 java.util.concurrent.ForkJoinPool.common 的值为 1或者服务器核心数小于等于2,都会导致不采用ForkJoinPool 中的线程,而是新起一个线程。

如果服务器只有两核,假如业务需要:现在起了20个completablefuture任务,若使用默认线程池,那么就会创建20个线程,20个线程并发执行在两个cpu上竞争稀缺的处理器和内存资源,浪费大量的时间在上下文切换上。

http://www.yayakq.cn/news/879068/

相关文章:

  • 平湖专业网站制作品牌网站建设怎么收费
  • 做宠物网站赚钱吗广告设计与制作网站
  • 淄博网站排名seo哈尔滨房地产网站建设
  • 平台网站建设网站廊坊网站自助建站
  • seo对网站的重要性做网站需要什么学历
  • 网站怎么做防御手机端快速建站工具
  • 广州怎么找做网站的公司超级简历免费模板
  • 专注于网站营销服务网页设计版面划分
  • 北京网站建设认知山西网站建设报价单
  • 外贸建站cms东台网站制作公司
  • 如何查看网站做没做竞价石狮服装城商家微网站建设
  • 网站制作公司技术部门seo优化关键词排名
  • 有什么做海报的网站吗wordpress仪表盘加速
  • 凡科做的网站好吗西安市未央区建设局官方网站
  • 装饰公司网站模板公司简历模板免费
  • 成都网站建设推来客网站系统报价阿里万网站建设
  • 网站建设流程策划方案德州seo外包
  • 东莞网络建站公司安徽省港航建设投资集团网站
  • 南浔区城乡建设局网站wordpress widget插件
  • 永州冷水滩网站建设app制作平台哪个好用
  • spark 网站开发选服务好的分销管理系统
  • excel免费模板网站百度开户
  • 越秀区pc端网站建设关于网页制作
  • 让互联网之光点亮生活北京网站优化排名推广
  • 台州做网站软件网络营销课程个人感悟
  • 南京网站设计搭建公司长沙优化推广外包
  • 泸州市建设厅网站个人网站cms
  • 住建部网站查询系统欧模网室内设计效果图
  • 做网站找谁好建筑信用信息查询平台
  • 网站怎么做网页游戏南京网站改版