当且仅当有空闲 CPU 时,我如何扩展以使用更多线程? 像 ThreadPoolExecutor 这样的东西,它在 cpu 核心空闲时使用更多线程,如果没有空闲则更少或只使用一个线程。
现状: 我的 Java 服务器应用程序处理请求并提供结果。 有一个 ThreadPoolExecutor 以合理数量的最大线程为请求提供服务,遵循以下原则:cpu 核心数 = 最大线程数。 执行的工作是 cpu 繁重的,并且有一些磁盘 IO (DB)。 代码是线性的,单线程的。 处理单个请求需要 50 到 500 毫秒。 有时每分钟只有几个请求,有时同时有 30 个请求。 具有 12 个内核的现代服务器可以很好地处理负载。 吞吐量不错,延迟还可以。
期望的改进: 当请求数量较少时(大多数情况下都是这种情况),许多 cpu 内核处于空闲状态。 在这种情况下,可以通过为单个请求多线程运行一些代码来改善延迟。 一些原型(prototype)设计显示出改进,但一旦我用更多的并发请求进行测试, 服务器发疯了。吞吐量下降,内存消耗过多。 30 个并发请求共享一个 10 个队列,这意味着 20 个等待时最多可以运行 10 个, 并且这 10 个中的每一个同时使用多达 8 个线程来实现并行性,对于一台机器来说似乎太多了 有 12 个内核(其中 6 个是虚拟内核)。
这在我看来是一个常见的用例,但我无法通过搜索找到信息。
1) 请求计数 一种想法是计算当前已处理请求的数量。如果为 1 或低,则执行更多并行操作, 如果高则不做任何事情并像以前一样继续单线程。 这听起来很容易实现。缺点是:请求计数器重置不能包含错误, 最后想想而且它实际上并不检查可用的 cpu,也许另一个进程也使用 cpu。 在我的例子中,机器专用于此应用程序,但仍然如此。
2) 实际cpu查询 我认为正确的方法是只询问 cpu,然后再决定。 由于 Java7 有 OperatingSystemMXBean.getSystemCpuLoad() 参见 http://docs.oracle.com/javase/7/docs/jre/api/management/extension/com/sun/management/OperatingSystemMXBean.html#getSystemCpuLoad() 但我找不到任何提到 getSystemCpuLoad 和 ThreadPoolExecutor 或类似内容的网页 关键字的组合,这告诉我这不是一条好路要走。 JavaDoc 说“返回整个系统的‘最近 cpu 使用率’”,我想知道是什么 “最近的 CPU 使用率”是指最近的时间以及该调用的费用。
我将这个问题搁置了一段时间,看看是否有更多的意见。没有。虽然我不喜欢对技术问题的“不行”的回答,但我现在要接受 Holger 的回答。他名声好,论据好,其他人都认可他的回答。 我自己对想法 2 进行了一些试验。我查询了任务中的 getSystemCpuLoad() 来决定他们自己的 ExecutorService 有多大。正如 Holger 所写,当有一个 SINGLE ExecutorService 时,可以很好地管理资源。但是一旦任务开始自己的任务,它们就不能 - 这对我来说没有成功。
最佳答案
没有基于“空闲 CPU”的限制方式,无论如何它都行不通。有关“免费 CPU”的信息在您获得后即已过时。假设你有 12 个并发运行的线程,同时检测到有一个空闲的 CPU 内核并决定安排一个子任务……
您可以做的是限制最大资源消耗,这在为 所有 任务使用最大线程数的单个 ExecutorService 时效果很好。
棘手的部分是任务对子任务结果的依赖性,这些子任务在稍后排队并且由于工作线程数量有限可能仍处于待处理状态。
如果任务检测到其子任务仍未决,则可以通过撤销并行执行来调整这一点。为此,请手动为子任务创建一个 FutureTask 并使用 execute 而不是 submit 安排它。然后在任务中正常进行,并在顺序执行中执行子任务的地方检查是否可以 remove ThreadPoolExecutor 中的 FutureTask。与 cancel 不同,这仅在尚未启动时有效,因此表明没有空闲线程。因此,如果 remove 返回 true,您可以就地执行子任务,让所有其他线程执行任务而不是子任务。否则,您可以等待结果。
在这个地方值得注意的是,如果任务适应 I/O 操作(或者可能等待子任务),线程数多于 CPU 内核是可以的。这里的重点是一个限制。
FutureTask<Integer> coWorker = new FutureTask<>(/* callable wrapping sub-task*/);
executor.execute(coWorker);
// proceed in the task’s sequence
if(executor.remove(coWorker)) coWorker.run();// do in-place if needed
subTaskResult=coWorker.get();
// proceed
关于基于可用 FREE cpu 的 Java 并发性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24409387/
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc