`
20921556
  • 浏览: 94767 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

如何在Java应用程序中动态的分配CPU资源

阅读更多
Java的线程调度操作在运行时是与平台无关的。一个多任务系统需要在任务之间实现QoS(Quality of Service)管理时,如果CPU资源的分配基于Java线程的优先级,那么它在不同平台上运行时的效果是很难预测的。本文利用协调式多任务模型,提出一个与平台无关、并且能在任务间动态分配CPU资源的方案。


现在,由于计算机系统已经从人机交互逐步向机机交互转化,计算机和计算机之间的业务对于时间的要求非常高。软件系统对于业务的支持已经不仅表现为对不同业务的逻辑和数据(算法+数据结构)支持,而且还表现为对同时处理不同任务的时效性(任务响应速度)支持。一般,任务响应的速度可以通过算法优化及并行运算分担负载等手段来提高。但是,用户业务逻辑的复杂度决定了算法优化的发挥空间,硬件规模决定了所能够承担负载的大小。我们利用Java平台的特点,借鉴协调式多任务思想,使CPU资源能够在任务间动态分配,从而为时间要求强的任务分配更多的CPU运行资源。这也可以充分利用现有硬件,为用户业务提供最大的保障。


用Java解决问题


本着软件系统结构和现实系统结构一致的思想,开发复杂业务服务的程序一般按照计算机任务和现实业务对应的思路,最终形成一个大规模的多任务系统。由于其跨平台性,Java系统可以随着业务的扩大,平滑地升级到各种硬件平台上。由于Java自身的发展及其应用场合的不断扩大,用它实现多任务系统已经成为当前的应用方向。在J2EE(Java2 Enterprise Edition)推出以后,Sun公司已经将Java的重心放在了服务器端(Server Side)系统的构造上。由于客户/服务器模型固有的多对一的关系,服务器端程序也必然是一个多任务系统。


在Java多任务应用中,动态地将CPU资源在任务间分配有很重要的意义。比如一个Internet服务商的系统往往有多种任务同时运行,有HTTP、FTP、MAIL等协议的支持,也有商务、娱乐、生活、咨询等业务的服务。在白天,网站希望系统的CPU资源尽量保障网上用户的服务质量,提高电子商务等任务的响应速度;晚上则希望让自己的娱乐服务和资料下载尽可能满足下班后人们的需要。另外,在新兴的网管(比如TMN, Telecommunication Management Network)等应用领域中,服务程序往往需要支持成千上万个并发响应事件的被管理对象(MO,Managed Object)。对于被管理对象执行的操作,不同用户在不同时刻往往有不同的时间要求。


方案选择


在考虑动态分配CPU资源的实施方案时,往往有以下两点要求:


1. 须充分利用现有硬件资源,在系统空闲时,让低优先级任务也能够得到系统所能给予的最快响应。


2.当硬件资源超负荷运行时,虽然系统中有大规模、多数量的任务不能处理,但它不应受影响,而能够顺利处理那些能够被处理的、最重要的高优先级任务。


多任务系统要用多线程实现的最简单方法就是将线程和任务一一对应,动态调整线程的优先级,利用线程调度来完成CPU资源在不同任务间动态分配。这种思路在以前使用本地化代码(Native Code),充分利用特定硬件和操作系统技巧的基础上是基本可行的。但在跨平台的Java环境中,这个思路对仅有小规模任务数的简单系统才可行,原因有以下两点:


1. Java的线程虽然在编程角度(API)是与平台无关的,但它的运行效果却和不同操作系统平台密切相关。为了利用更多的CPU资源,Java中的一个线程(Thread)就对应着不同操作系统下的一个真实线程。因为Java虚拟机没有实现线程的调度,所以这些Java的线程在不同操作系统调度下运行的差异性也就比较明显。例如在Windows系统中,不仅线程的优先级少于Java API参数规定的十个优先级,而且微软明确反对程序员动态调整线程优先级。即使在操作系统中有足够的优先权,让线程优先级的参数和真实线程的优先级对应,不同操作系统的调度方式也会有许多不同。这最终会造成代码在不同平台上的行为变得不可预测。这就很难满足复杂的、大规模并发任务的众多优先级需求,从而很难达到用户业务需要达到的效果。


2. 由于在Java系统中,线程被包装在一个Java语言的对象类—Thread中,所以为了完成Java语言对象和操作系统线程的对应,Java线程的系统开销还是比较大的(在NT 4.0中,平均每个线程大致占用30KB内存)。因此如果让Thread对象个数和成千上万的任务数同比例增长,就显然是不合理的。


综上所述,根据并发多任务的大规模需求和Java平台固有的特点,想要利用Java Thread对象的优先级调整CPU资源的分配是非常困难的,所以应该尽量避免让线程和任务直接对应,也尽量避免使用操作系统线程优先级的调度机制。


解决方案


根据以上分析,问题的症结在于:多任务系统中的任务在Java语言中的对应以及任务间的相互调度。


从本质上看,一个任务就是一系列对象方法的调用序列,与Java的Thread对象或者别的类的对象没有必然联系。在避免使用不同操作系统线程调度且同时Java虚拟机又没有线程调度能力的情况下,要想构造一个协调式多任务系统,让各个任务相互配合就成了最直接的思路。协调式多任务系统一般有以下特点:


1. 任务由消息驱动,消息的响应代码完成任务逻辑的处理;


2. 消息队列完成消息的存储和管理,从而利用消息处理的次序体现任务优先级的不同;


3. 任务中耗时的消息响应逻辑能够主动放弃CPU资源,让别的任务执行(像Windows 3.1中的Yield函数、Visual Basic中的DoEvents语句)。


可能出于巧合,Java语言具有构造协调式多任务系统天然的条件。Java对象的方法不仅是一个函数调用,它还是一个java.lang.reflect.Method类的对象。而所有对象的方法都可以通过Method类的invoke方法调用。如果能使每个任务所对应的一系列方法全部以对象形式包装成消息,放到消息队列中,然后再按照自己的优先级算法将队列中的消息取出,执行其Method对象的invoke调用,那么一个基本的协调式多任务系统就形成了。其中,任务的优先级和线程的优先级没有绑定关系。该系统的主体调度函数可以设置成一个“死循环”,按照需要的优先级算法处理消息队列。对于有多重循环、外设等待等耗时操作的消息响应函数,可以在响应函数内部递归调用主体调度函数,这一次调用把原来的“死循环”改成在消息队列长度减少到一定程度(或者为空)后退出。退出后,函数返回,执行刚才没有完成的消息响应逻辑,这样就非常自然地实现了协调式系统中任务主动放弃CPU资源的要求。


如果仅仅做到这一步,完成一个像Windows 3.1中的多任务系统,实际只用了一个线程,没有利用Java多线程的特点。应该注意到,虽然Java系统中线程调度与平台相关,但是相同优先级的线程之间分时运行的特点基本上是不受特定平台影响的。各个相同优先级的线程共享CPU资源,而线程又被映射成了Java语言中的Thread对象。这些对象就可以被认为是CPU资源的代表。Thread与线程执行代码主体的接口—Runnable之间是多对一的关系。一个Runnable可以被多个Thread执行。只要将Runnable的执行代码设置成上述的消息调度函数,并和消息队列对应上,那么就可以通过控制为它服务的Thread个数来决定消息队列执行的快慢,并且在运行时可以动态地新增(new)和退出Thread对象。这样就能任意调整不同消息队列在执行时所占用CPU资源的多少。至此,任何一个Java调用都可以在Thread个数不同的消息队列中选择,并可以调整这些消息队列服务的Thread个数,从而实现在运行时调整任务所占用的CPU资源。


纵观整个方案,由于仅仅基于Java语言固有的Method对象,不同任务间动态分配CPU资源并没有对任务的性质及其处理流程有任何限制,那么在消息队列中没有高优先级消息时,低优先级消息的处理函数自然会全部占用CPU资源。在不同消息队列处理速度任意设置时,并没有将特定的消息限制在快的或者慢的消息队列上。如果系统的负荷超出(比如消息队列长度超过一定限制),只要将队列中低优先级消息换出或者拒绝不能处理的消息进入,那么系统的运行就可以基本上不受负荷压力的影响,从而最大保障用户的关键业务需求。


当然,协调式多任务的思想也有其局限性,主要就是它的调度粒度比较大。系统能够保证的粒度是一次消息处理过程。如果消息处理逻辑非常费时,那么编程人员就必须再处理函数内部,让系统主动让出CPU资源。这虽然需要在处理消息响应逻辑时增加一个考虑因素,但是,在Windows系统盛行的今天,这是一个已经被普遍接受的思路。由于方案中并没有局限为消息队列服务的线程数目,所以一个长时间的消息响应只会影响一个线程,而不会对整个系统产生致命的影响。除了调度粒度的问题以外,还有访问消息队列操作在各个线程间互斥的问题。取出消息的过程是串行化的,因此对于这一瓶颈的解决方案就是:假设取出一条消息的操作相对于处理消息的消耗可以忽略不计,那么对于多次调用且仅有两三行响应逻辑的消息,编程人员通过函数调用就可以直接执行。


前面比较详细地阐述了多任务系统中任务的划分以及执行等内容。虽然这些是一个系统的核心,但是在一个实用的系统中,还需要任务间的同步、互斥等机制。在上述框架内,互斥可以简单地用Java的Synchronized机制实现。由于任务可以主动让出执行权限,要实现等待(Wait任务中止)和通知(Notify任务继续),从而实现任务同步也就比较容易了。
分享到:
评论

相关推荐

    CPU资源在Java中的动态分配.pdf

    Java线程调度在运行时是平台无关的,这意味着Java程序可以在不同的操作系统上运行,但这也带来了CPU资源分配的不确定性。当基于Java线程优先级进行CPU资源分配时,不同平台上的表现可能会有所不同。 为了克服这一...

    测量Java应用程序的CPU和内存占用率

    在Java应用程序的性能优化过程中,了解应用程序的CPU和内存使用情况至关重要。这可以帮助开发人员识别潜在的性能瓶颈,优化资源分配,确保程序高效运行。Java标准库虽然提供了诸如堆栈大小的测量方法,但并不直接...

    【原创】java程序cpu占用过高问题分析

    在Java编程中,CPU占用过高是一个常见的性能问题,可能由多种因素引起,包括但不限于不当的算法选择、线程过多、循环优化不足、垃圾回收(GC)问题、内存泄漏或资源竞争等。这篇原创博客“【原创】java程序cpu占用过...

    基于java的Visualvm 基于JAVA的CPU硬件资源管理器源程序.zip

    在本压缩包"基于java的Visualvm 基于JAVA的CPU硬件资源管理器源程序.zip"中,我们可能找到了VisualVM用于监控和管理Java应用程序CPU资源的部分源代码。 1. **VisualVM概述**: VisualVM是一款跨平台的Java诊断工具...

    用java获取CPU占用率

    在IT领域,特别是系统监控与性能分析中,获取CPU占用率是评估系统健康状况和优化资源分配的关键步骤。本文将详细解析如何使用Java语言来获取CPU占用率,这不仅涉及了基本的Java编程技巧,还深入到了操作系统级别的...

    Visualvm 基于JAVA的CPU硬件资源管理器源程序.rar

    这款工具对于理解Java应用程序如何使用系统资源,尤其是CPU和内存,非常有帮助。 在"Visualvm 基于JAVA的CPU硬件资源管理器源程序.rar"这个压缩包中,可能包含的是VisualVM的源代码或与其相关的扩展模块。这为我们...

    java检测程序系统

    在这个监控程序中,JNI可能被用来调用操作系统级别的API,获取更底层、更详细的系统资源使用信息,比如CPU的实时负载、内存分配细节或网络接口的传输速率等。通过JNI,Java程序能够利用C/C++等本地代码的高效性,...

    基于Java的实例源码-Visualvm 基于JAVA的CPU硬件资源管理器源程序.zip

    在Java开发中,了解和优化应用程序对CPU资源的使用是至关重要的。VisualVM是一款强大的Java性能分析工具,它提供了丰富的功能,帮助开发者深入洞察应用程序的运行状况,特别是CPU的使用情况。本文将详细探讨基于Java...

    java源码:Visualvm 基于JAVA的CPU硬件资源管理器源程序.rar

    开发者可以通过源码学习如何分析和优化Java应用的CPU使用、内存分配、线程调度等方面,从而提升应用的性能。 7. **插件机制** VisualVM的可扩展性体现在其插件系统上。开发者可以编写自定义插件,扩展其功能,例如...

    百宝箱业务应用程序开发规范-JAVA分册

    《百宝箱业务应用程序开发规范—JAVA分册》是中国移动通信集团针对Java业务开发制定的一套详细指导文档,旨在规范和标准化Java应用程序在移动终端上的开发流程和技术实现。此文档覆盖了从业务类型定义、系统架构描述...

    基于java的开发源码-Visualvm 基于JAVA的CPU硬件资源管理器源程序.zip

    本资料包含的源码是VisualVM针对Java应用程序的CPU硬件资源管理部分,通过分析这些源代码,我们可以深入了解Java在管理CPU资源方面的细节。 VisualVM提供了丰富的功能,包括内存分析、线程监控、类加载信息、JMX...

    基于Java的Visualvm 基于JAVA的CPU硬件资源管理器源程序.zip

    1. **性能分析**:VisualVM可以监控Java应用程序的CPU使用率、内存消耗、线程活动等关键指标。通过这些数据,开发者可以识别性能瓶颈,优化代码执行效率。 2. **内存检测**:对于内存泄漏问题,VisualVM提供了堆...

    CPU资源占用100%解决方法

    1. **检查运行中的进程**:使用任务管理器(Windows)或活动监视器(MacOS)查看哪些应用程序或进程占用了大量CPU资源。通常,恶意软件、病毒或后台程序异常都会导致这种情况。找到高CPU占用的进程后,可以尝试结束...

    java程序中的内存分配问题javalearnsa资料分享

    在Java编程语言中,内存管理是程序设计的重要组成部分,它涉及到如何有效地分配、使用和释放内存资源。Java的内存分配主要由垃圾收集器(Garbage Collector, GC)自动进行,但理解其工作原理对于优化程序性能和避免...

    cpu进程调度 java编写

    在IT领域,操作系统是计算机系统的核心,它负责管理和协调计算机硬件和软件资源,其中包括对CPU时间的分配。本文将深入探讨“CPU进程调度”这一重要概念,并基于Java语言的实现进行详细阐述。在这个课程设计中,我们...

    深入Java核心 Java内存分配原理精讲

    堆内存的动态分配使得Java程序能够灵活地管理内存资源,但同时也带来了较高的内存消耗和相对较低的访问速度。 ### 三、常量池解析 常量池在编译期就已经确定,包含了类和接口的全限定名、字段和方法的名称和描述符...

    Visualvm 基于JAVA的CPU硬件资源管理器源程序

    - **CPU剖析**:Visualvm可以实时监控Java应用程序的CPU使用情况,包括方法调用时间、线程执行情况,帮助开发者定位性能瓶颈。 - **内存分析**:提供堆内存和对象的详细视图,帮助找出内存泄漏和过度对象创建的...

    Java并发程序设计教程

    在Java编程领域,并发程序设计是一项至关重要的技能,特别是在多核处理器和分布式系统环境中。Java提供了丰富的并发工具和API,使得开发者能够有效地编写出高效、安全的并发应用程序。本教程将深入探讨Java并发编程...

    java小程序中动画及音乐多线程的应用源码下载

    在本项目中,“java小程序中动画及音乐多线程的应用源码下载”是一个示例,它展示了如何在Java应用程序中实现多线程来处理动画和音频播放,以提升用户体验,避免因为这些耗时操作阻塞主线程导致应用无响应。...

Global site tag (gtag.js) - Google Analytics