Java应用程序中定时执行任务资料讲解_第1页
Java应用程序中定时执行任务资料讲解_第2页
Java应用程序中定时执行任务资料讲解_第3页
Java应用程序中定时执行任务资料讲解_第4页
Java应用程序中定时执行任务资料讲解_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Good is good, but better carries it.精益求精,善益求善。Java应用程序中定时执行任务所有类型的Java应用程序一般都需要计划重复执行的任务。企业应用程序需要计划每日的日志或者晚间批处理过程。一个J2SE或者J2ME日历应用程序需要根据用户的约定计划闹铃时间。不过,标准的调度类Timer和TimerTask没有足够的灵活性,无法支持通常需要的计划任务类型。在本文中,Java开发人员TomWhite向您展示了如何构建一个简单通用的计划框架,以用于执行任意复杂的计划任务。我将把java.util.Timer和java.util.TimerTask统称为Java计

2、时器框架,它们使程序员可以很容易地计划简单的任务(注意这些类也可用于J2ME中)。在Java2SDK,StandardEdition,Version1.3中引入这个框架之前,开发人员必须编写自己的调度程序,这需要花费很大精力来处理线程和复杂的Object.wait()方法。不过,Java计时器框架没有足够的能力来满足许多应用程序的计划要求。甚至一项需要在每天同一时间重复执行的任务,也不能直接使用Timer来计划,因为在夏令时开始和结束时会出现时间跳跃。本文展示了一个通用的Timer和TimerTask计划框架,从而允许更灵活的计划任务。这个框架非常简单它包括两个类和一个接口并且容易掌握。如果您

3、习惯于使用Java定时器框架,那么您应该可以很快地掌握这个计划框架。计划单次任务计划框架建立在Java定时器框架类的基础之上。因此,在解释如何使用计划框架以及如何实现它之前,我们将首先看看如何用这些类进行计划。想像一个煮蛋计时器,在数分钟之后(这时蛋煮好了)它会发出声音提醒您。清单1中的代码构成了一个简单的煮蛋计时器的基本结构,它用Java语言编写:清单1.EggTimer类packageorg.tiling.scheduling.examples;importjava.util.Timer;importjava.util.TimerTask;publicclassEggTimerprivat

4、efinalTimertimer=newTimer();privatefinalintminutes;publicEggTimer(intminutes)this.minutes=minutes;publicvoidstart()timer.schedule(newTimerTask()publicvoidrun()playSound();timer.cancel();privatevoidplaySound()System.out.println(Youreggisready!);/Startanewthreadtoplayasound.,minutes*60*1000);publicsta

5、ticvoidmain(Stringargs)EggTimereggTimer=newEggTimer(2);eggTimer.start();EggTimer实例拥有一个Timer实例,用于提供必要的计划。用start()方法启动煮蛋计时器后,它就计划了一个TimerTask,在指定的分钟数之后执行。时间到了,Timer就在后台调用TimerTask的start()方法,这会使它发出声音。在取消计时器后这个应用程序就会中止。计划重复执行的任务通过指定一个固定的执行频率或者固定的执行时间间隔,Timer可以对重复执行的任务进行计划。不过,有许多应用程序要求更复杂的计划。例如,每天清晨在同一时间

6、发出叫醒铃声的闹钟不能简单地使用固定的计划频率86400000毫秒(24小时),因为在钟拨快或者拨慢(如果您的时区使用夏令时)的那些天里,叫醒可能过晚或者过早。解决方案是使用日历算法计算每日事件下一次计划发生的时间。而这正是计划框架所支持的。考虑清单2中的AlarmClock实现:清单2.AlarmClock类packageorg.tiling.scheduling.examples;importjava.text.SimpleDateFormat;importjava.util.Date;importorg.tiling.scheduling.Scheduler;importorg.tili

7、ng.scheduling.SchedulerTask;importorg.tiling.scheduling.examples.iterators.DailyIterator;publicclassAlarmClockprivatefinalSchedulerscheduler=newScheduler();privatefinalSimpleDateFormatdateFormat=newSimpleDateFormat(ddMMMyyyyHH:mm:ss.SSS);privatefinalinthourOfDay,minute,second;publicAlarmClock(inthou

8、rOfDay,intminute,intsecond)this.hourOfDay=hourOfDay;this.minute=minute;this.second=second;publicvoidstart()scheduler.schedule(newSchedulerTask()publicvoidrun()soundAlarm();privatevoidsoundAlarm()System.out.println(Wakeup!+It"s+dateFormat.format(newDate();/Startanewthreadtosoundanalarm.,newDailyI

9、terator(hourOfDay,minute,second);publicstaticvoidmain(Stringargs)AlarmClockalarmClock=newAlarmClock(7,0,0);alarmClock.start();注意这段代码与煮蛋计时器应用程序非常相似。AlarmClock实例拥有一个Scheduler(而不是Timer)实例,用于提供必要的计划。启动后,这个闹钟对SchedulerTask(而不是TimerTask)进行调度用以发出报警声。这个闹钟不是计划一个任务在固定的延迟时间后执行,而是用DailyIterator类描述其计划。在这里,它只是计划任

10、务在每天上午7:00执行。下面是一个正常运行情况下的输出:Wakeup!It"s24Aug200307:00:00.023Wakeup!It"s25Aug200307:00:00.001Wakeup!It"s26Aug200307:00:00.058Wakeup!It"s27Aug200307:00:00.015Wakeup!It"s28Aug200307:00:00.002.DailyIterator实现了ScheduleIterator,这是一个将SchedulerTask的计划执行时间指定为一系列java.util.Date对象的接口。然后next

11、()方法按时间先后顺序迭代Date对象。返回值null会使任务取消(即它再也不会运行)这样的话,试图再次计划将会抛出一个异常。清单3包含ScheduleIterator接口:清单3.ScheduleIterator接口packageorg.tiling.scheduling;importjava.util.Date;publicinterfaceScheduleIteratorpublicDatenext();DailyIterator的next()方法返回表示每天同一时间(上午7:00)的Date对象,如清单4所示。所以,如果对新构建的next()类调用next(),那么将会得到传递给构造函

12、数的那个日期当天或者后面一天的7:00AM。再次调用next()会返回后一天的7:00AM,如此重复。为了实现这种行为,DailyIterator使用了java.util.Calendar实例。构造函数会在日历中加上一天,对日历的这种设置使得第一次调用next()会返回正确的Date。注意代码没有明确地提到夏令时修正,因为Calendar实现(在本例中是GregorianCalendar)负责对此进行处理,所以不需要这样做。清单4.DailyIterator类packageorg.tiling.scheduling.examples.iterators;importorg.tiling.sch

13、eduling.ScheduleIterator;importjava.util.Calendar;importjava.util.Date;/*ADailyIteratorclassreturnsasequenceofdatesonsubsequentdays*representingthesametimeeachday.*/publicclassDailyIteratorimplementsScheduleIteratorprivatefinalinthourOfDay,minute,second;privatefinalCalendarcalendar=Calendar.getInsta

14、nce();publicDailyIterator(inthourOfDay,intminute,intsecond)this(hourOfDay,minute,second,newDate();publicDailyIterator(inthourOfDay,intminute,intsecond,Datedate)this.hourOfDay=hourOfDay;this.minute=minute;this.second=second;calendar.setTime(date);calendar.set(Calendar.HOUR_OF_DAY,hourOfDay);calendar.

15、set(Calendar.MINUTE,minute);calendar.set(Calendar.SECOND,second);calendar.set(Calendar.MILLISECOND,0);if(!calendar.getTime().before(date)calendar.add(Calendar.DATE,-1);publicDatenext()calendar.add(Calendar.DATE,1);returncalendar.getTime();HYPERLINK/pub/article/c322_a78111_p1.html实现计划框架在上一节,我们学习了如何使用

16、计划框架,并将它与Java定时器框架进行了比较。下面,我将向您展示如何实现这个框架。除了清单3中展示的ScheduleIterator接口,构成这个框架的还有另外两个类Scheduler和SchedulerTask。这些类实际上在内部使用Timer和SchedulerTask,因为计划其实就是一系列的单次定时器。清单5和6显示了这两个类的源代码:清单5.Schedulerpackageorg.tiling.scheduling;importjava.util.Date;importjava.util.Timer;importjava.util.TimerTask;publicclassSche

17、dulerclassSchedulerTimerTaskextendsTimerTaskprivateSchedulerTaskschedulerTask;privateScheduleIteratoriterator;publicSchedulerTimerTask(SchedulerTaskschedulerTask,ScheduleIteratoriterator)this.schedulerTask=schedulerTask;this.iterator=iterator;publicvoidrun()schedulerTask.run();reschedule(schedulerTa

18、sk,iterator);privatefinalTimertimer=newTimer();publicScheduler()publicvoidcancel()timer.cancel();publicvoidschedule(SchedulerTaskschedulerTask,ScheduleIteratoriterator)Datetime=iterator.next();if(time=null)schedulerTask.cancel();elsesynchronized(schedulerTask.lock)if(schedulerTask.state!=SchedulerTa

19、sk.VIRGIN)thrownewIllegalStateException(Taskalreadyscheduled+orcancelled);schedulerTask.state=SchedulerTask.SCHEDULED;schedulerTask.timerTask=newSchedulerTimerTask(schedulerTask,iterator);timer.schedule(schedulerTask.timerTask,time);privatevoidreschedule(SchedulerTaskschedulerTask,ScheduleIteratorit

20、erator)Datetime=iterator.next();if(time=null)schedulerTask.cancel();elsesynchronized(schedulerTask.lock)if(schedulerTask.state!=SchedulerTask.CANCELLED)schedulerTask.timerTask=newSchedulerTimerTask(schedulerTask,iterator);timer.schedule(schedulerTask.timerTask,time);清单6显示了SchedulerTask类的源代码:packageo

21、rg.tiling.scheduling;importjava.util.TimerTask;publicabstractclassSchedulerTaskimplementsRunnablefinalObjectlock=newObject();intstate=VIRGIN;staticfinalintVIRGIN=0;staticfinalintSCHEDULED=1;staticfinalintCANCELLED=2;TimerTasktimerTask;protectedSchedulerTask()publicabstractvoidrun();publicbooleancanc

22、el()synchronized(lock)if(timerTask!=null)timerTask.cancel();booleanresult=(state=SCHEDULED);state=CANCELLED;returnresult;publiclongscheduledExecutionTime()synchronized(lock)returntimerTask=null?0:timerTask.scheduledExecutionTime();就像煮蛋计时器,Scheduler的每一个实例都拥有Timer的一个实例,用于提供底层计划。Scheduler并没有像实现煮蛋计时器时那样

23、使用一个单次定时器,它将一组单次定时器串接在一起,以便在由ScheduleIterator指定的各个时间执行SchedulerTask类。考虑Scheduler上的publicschedule()方法这是计划的入口点,因为它是客户调用的方法(在取消任务一节中将描述仅有的另一个public方法cancel())。通过调用ScheduleIterator接口的next(),发现第一次执行SchedulerTask的时间。然后通过调用底层Timer类的单次schedule()方法,启动计划在这一时刻执行。为单次执行提供的TimerTask对象是嵌入的SchedulerTimerTask类的一个实例,

24、它包装了任务和迭代器(iterator)。在指定的时间,调用嵌入类的run()方法,它使用包装的任务和迭代器引用以便重新计划任务的下一次执行。reschedule()方法与schedule()方法非常相似,只不过它是private的,并且执行一组稍有不同的SchedulerTask状态检查。重新计划过程反复重复,为每次计划执行构造一个新的嵌入类实例,直到任务或者调度程序被取消(或者JVM关闭)。类似于TimerTask,SchedulerTask在其生命周期中要经历一系列的状态。创建后,它处于VIRGIN状态,这表明它从没有计划过。计划以后,它就变为SCHEDULED状态,再用下面描述的方法之

25、一取消任务后,它就变为CANCELLED状态。管理正确的状态转变如保证不对一个非VIRGIN状态的任务进行两次计划增加了Scheduler和SchedulerTask类的复杂性。在进行可能改变任务状态的操作时,代码必须同步任务的锁对象。取消任务取消计划任务有三种方式。第一种是调用SchedulerTask的cancel()方法。这很像调用TimerTask的cancel()方法:任务再也不会运行了,不过已经运行的任务仍会运行完成。cancel()方法的返回值是一个布尔值,表示如果没有调用cancel()的话,计划的任务是否还会运行。更准确地说,如果任务在调用cancel()之前是SCHEDUL

26、ED状态,那么它就返回true。如果试图再次计划一个取消的(甚至是已计划的)任务,那么Scheduler就会抛出一个IllegalStateException。取消计划任务的第二种方式是让ScheduleIterator返回null。这只是第一种方式的简化操作,因为Scheduler类调用SchedulerTask类的cancel()方法。如果您想用迭代器而不是任务来控制计划停止时间时,就用得上这种取消任务的方式了。第三种方式是通过调用其cancel()方法取消整个Scheduler。这会取消调试程序的所有任务,并使它不能再计划任何任务。扩展cron实用程序可以将计划框架比作UNIX的cron

27、实用程序,只不过计划次数的规定是强制性而不是声明性的。例如,在AlarmClock实现中使用的DailyIterator类,它的计划与cron作业的计划相同,都是由以07*开始的crontab项指定的(这些字段分别指定分钟、小时、日、月和星期)。不过,计划框架比cron更灵活。想像一个在早晨打开热水的HeatingController应用程序。我想指示它“在每个工作日上午8:00打开热水,在周未上午9:00打开热水”。使用cron,我需要两个crontab项(08*1,2,3,4,5和09*6,7)。而使用ScheduleIterator的解决方案更简洁一些,因为我可以使用复合(composi

28、tion)来定义单一迭代器。清单7显示了其中的一种方法:清单7.用复合定义单一迭代器intweekdays=newintCalendar.MONDAY,Calendar.TUESDAY,Calendar.WEDNESDAY,Calendar.THURSDAY,Calendar.FRIDAY;intweekend=newintCalendar.SATURDAY,Calendar.SUNDAY;ScheduleIteratori=newCompositeIterator(newScheduleIteratornewRestrictedDailyIterator(8,0,0,weekdays),ne

29、wRestrictedDailyIterator(9,0,0,weekend);RestrictedDailyIterator类很像DailyIterator,只不过它限制为只在一周的特定日子里运行,而一个CompositeIterator类取得一组ScheduleIterators,并将日期正确排列到单个计划中。有许多计划是cron无法生成的,但是ScheduleIterator实现却可以。例如,“每个月的最后一天”描述的计划可以用标准Java日历算法来实现(用Calendar类),而用cron则无法表达它。应用程序甚至无需使用Calendar类。在本文的源代码(请参阅参考资料)中,我加入了

30、一个安全灯控制器的例子,它按“在日落之前15分钟开灯”这一计划运行。这个实现使用了CalendricalCalculationsSoftwarePackage,用于计算当地(给定经度和纬度)的日落时间。实时保证在编写使用计划的应用程序时,一定要了解框架在时间方面有什么保证。我的任务是提前还是延迟执行?如果有提前或者延迟,偏差最大值是多少?不幸的是,对这些问题没有简单的答案。不过在实际中,它的行为对于很多应用程序已经足够了。下面的讨论假设系统时钟是正确的。因为Scheduler将计划委托给Timer类,Scheduler可以做出的实时保证与Timer的一样。Timer用Object.wait(l

31、ong)方法计划任务。当前线程要等待直到唤醒它,唤醒可能出于以下原因之一:1.另一个线程调用对象的notify()或者notifyAll()方法。2.线程被另一个线程中断。3.在没有通知的情况下,线程被唤醒(称为spuriouswakeup,JoshuaBloch的EffectiveJavaProgrammingLanguageGuide一书中Item50对其进行了描述。4.规定的时间已到。对于Timer类来说,第一种可能性是不会发生的,因为对其调用wait()的对象是私有的。即便如此,Timer实现仍然针对前三种提前唤醒的原因进行了保护,这样保证了线程在规定时间后才唤醒。目前,Object.

32、wait(long)的文档注释声明,它会在规定的时间“前后”苏醒,所以线程有可能提前唤醒。在本例中,Timer会让另一个wait()执行(scheduledExecutionTime-System.currentTimeMillis())毫秒,从而保证任务永远不会提前执行。任务是否会延迟执行呢?会的。延迟执行有两个主要原因:线程计划和垃圾收集。Java语言规范故意没有对线程计划做严格的规定。这是因为Java平台是通用的,并针对于大范围的硬件及其相关的操作系统。虽然大多数JVM实现都有公平的线程调度程序,但是这一点没有任何保证当然,各个实现都有不同的为线程分配处理器时间的策略。因此,当Timer

33、线程在分配的时间后唤醒时,它实际执行其任务的时间取决于JVM的线程计划策略,以及有多少其他线程竞争处理器时间。因此,要减缓任务的延迟执行,应该将应用程序中可运行的线程数降至最少。为了做到这一点,可以考虑在一个单独的JVM中运行调度程序。对于创建大量对象的大型应用程序,JVM花在垃圾收集(GC)上的时间会非常多。默认情况下,进行GC时,整个应用程序都必须等待它完成,这可能要有几秒钟甚至更长的时间(Java应用程序启动器的命令行选项-verbose:gc将导致向控制台报告每一次GC事件)。要将这些由GC引起的暂停(这可能会影响快速任务的执行)降至最少,应该将应用程序创建的对象的数目降至最低。同样,

34、在单独的JVM中运行计划代码是有帮助的。同时,可以试用几个微调选项以尽可能地减少GC暂停。例如,增量GC会尽量将主收集的代价分散到几个小的收集上。当然这会降低GC的效率,但是这可能是时间计划的一个可接受的代价。被计划到什么时候?如果任务本身能监视并记录所有延迟执行的实例,那么对于确定任务是否能按时运行会很有帮助。SchedulerTask类似于TimerTask,有一个scheduledExecutionTime()方法,它返回计划任务最近一次执行的时间。在任务的run()方法开始时,对表达式System.currentTimeMillis()-scheduledExecutionTime()

35、进行判断,可以让您确定任务延迟了多久执行(以毫秒为单位)。可以记录这个值,以便生成一个关于延迟执行的分布统计。可以用这个值决定任务应当采取什么动作例如,如果任务太迟了,那么它可能什么也不做。在遵循上述原则的情况下,如果应用程序需要更严格的时间保证,可参考Java的实时规范。结束语在本文中,我介绍了Java定时器框架的一个简单增强,它使得灵活的计划策略成为可能。新的框架实质上是更通用的cron事实上,将cron实现为一个ScheduleIterator接口,用以替换单纯的Javacron,这是非常有用的。虽然没有提供严格的实时保证,但是许多需要计划定期任务的通用Java应用程序都可以使用这一框架

36、。参考资料下载本文中使用的HYPERLINK/software/developer/library/j-schedule.zip源代码。“HYPERLINK/docs/hotspot/gc/TuningGarbageCollectionwiththe1.3.1JavaVirtualMachine”是Sun的一篇非常有用的文章,它给出了关于如何最小化GC暂停时间的提示。要获得developerWorks中有关GC的更多信息,请参阅以下文章:“HYPERLINK/developerWorks/cn/java/j-jtp10283/Java理论与实践:垃圾收集简史”(2003年10月)。“HYPER

37、LINK/developerworks/ibm/library/i-incrcomp/Mashthattrash”(2003年7月)。“HYPERLINK/developerworks/ibm/library/i-gctroub/Fine-tuningJavagarbagecollectionperformance”(2003年1月)。“HYPERLINK/developerworks/ibm/library/i-garbage1/Sensiblesanitation,Part1”(2002年8月)。“HYPERLINK/developerworks/ibm/library/i-garbage

38、2/Sensiblesanitation,Part2”(2002年8月)。“HYPERLINK/developerworks/ibm/library/i-garbage3/Sensiblesanitation,Part3”(2002年9月)。在“HYPERLINK/developerWorks/cn/java/j-jtp1126/Java理论与实践:并发在一定程度上使一切变得简单”(developerWorks,2002年11月)中,BrianGoetz讨论了DougLea的util.concurrent库,这是一个并发实用工具类的宝库。BrianGoetz的另一篇文章“HYPERLINK/d

39、eveloperworks/java/library/j-threads2.htmlThreadinglightly,Part2:Reducingcontention”(developerWorks,2001年9月)分析了线程竞用以及如何减少它。关于作者TomWhite是Kizoom的首席Java开发人员,Kizoom是一家领先的英国软件公司,提供向移动设备发送个性化旅行信息的服务。客户包括英国的国家火车操作员、伦敦公共交通系统(nationaltrainoperator),以及英国国家公共汽车公司。自1999年成立以来,Kizoom使用了极限编程的所有方法。自1996年起,Tom一直全职编写

40、Java程序,使用了大部分标准和企业JavaAPI,编写了从客户SwingGUI和图形到后端消息传送系统等各种应用程序。他在剑桥大学获得了一级荣誉学位(firstclasshonoursdegree)。工作之余,Tom喜欢逗他的小女儿开心,观看20世纪30年代的好莱坞电影。可以通过tom与Tom联系。TuningGarbageCollectionwiththe1.3.1JavaVirtualMachineSeealsoHYPERLINK/docs/hotspot/index.htmlPerformanceDocsIntroductionTheJava2Platformisincreasingl

41、yusedforlargeserverapplicationssuchaswebservices.Theseapplicationsdemandscalability,anddirectlybenefitfromlargenumbersofthreads,processors,socketsandmemory.Yetbigironperformancehasareputationasanartform,requiringspecialexpertisebeyondwhatisneededforperformanceonsmallersystems.Fortunately,theJavaVirt

42、ualMachine(JVM)*andSolarisoperatingenvironmentprovideeffectiveimplementationsofthreads,I/Oandmemorymanagement.Thisdocumentaddressesacommonspeedbumpontheroadtoscalablehighperformance:poorlytunedgarbagecollection(GC).Amdahlobservedthatmostworkloadscannotbeperfectlyparallelized;someportionisalwaysseque

43、ntialanddoesnotbenefitfromparallelism.ThisisalsotruefortheJava2Platform.Inparticular,JVMsuptoandincludingversion1.3.1donothaveparallelgarbagecollection,sotheimpactofGConamultiprocessorsystemgrowsrelativetoanotherwiseparallelapplication.Thegraphbelowmodelsanidealsystemthatisperfectlyscalablewiththeex

44、ceptionofGC.Thetopline(red)isanapplicationspendingonly1%ofthetimeinGConauniprocessor;thistranslatesintomorethan20%lossinthroughputat32processors.At10%,notconsideredanoutrageousamountoftimeinGCinuniprocessorapplications,morethan75%ofthroughputislostwhenscalingup.Thisdemonstratesthatissuesthatappearlo

45、stinthenoisewhendevelopingonsmallsystemsmaybecomeprincipalbottleneckswhenscalingup.Thesilverliningisthatsmallimprovementsinsuchabottleneckcanproducelargegainsinperformance.Forasufficientlylargesystemitbecomeswellworthwhiletotunegarbagecollection.Thisdocumentiswrittenfromtheperspectiveof1.3.1JVMonthe

46、Solaris(SPARCPlatformEdition)operatingenvironment,becausethatplatformprovidesthemostscalablehardware/softwareJava2platformtoday.However,thedescriptivetextappliestoothersupportedplatforms,includingLinux,MicrosoftWindows,andtheSolaris(IntelArchitecture)operatingenvironment,totheextentthatscalablehardw

47、areisavailable.Althoughcommandlineoptionsareconsistentacrossplatforms,someplatformsmayhavedifferentdefaultsthandescribedhere.GenerationsOneofJava2Platformsgreatstrengthsisthatitshieldsthesubstantialcomplexityofmemoryallocationandgarbagecollectionfromthedeveloper.However,onceGChasbecometheprincipalbo

48、ttleneck,itbecomesworthunderstandingaspectsofthishiddenimplementation.Garbagecollectorsmakeassumptionsaboutthewayapplicationsuseobjects,andthesearereflectedintunableparametersthatcanbeadjustedforimprovedperformancewithoutsacrificingthepoweroftheabstraction.Anobjectisgarbagewhenitcannolongerbereached

49、fromanypointerintherunningprogram.Themoststraightforwardgarbagecollectionalgorithmssimplyiterateovereveryreachableobject;anyobjectsleftoverarethenknowntobegarbage.Thisapproachtakestimeproportionaltothenumberoflivingobjects,whichisprohibitiveforlargeapplicationsmaintaininglotsoflivingdata.The1.3JVMin

50、corporatesanumberofdifferentgarbagecollectionalgorithmsthatarecombinedusinggenerationalcollection.Whilenaivegarbagecollectionexamineseverylivingobjectintheheap,generationalcollectionexploitsseveralempiricallyobservedpropertiesofmostapplicationstoavoidextrawork.Themostimportantofthesepropertiesisinfa

51、ntmortality.Theblueareainthediagrambelowisatypicaldistributionforthelifetimesofobjects.Thesharppeakattheleftrepresentsobjectsthatcanbereclaimedshortlyafterbeingallocated.Iteratorobjects,forexample,areoftenaliveforthedurationofasingleloop.Someobjectsdolivelonger,andsothedistributionstretchesouttothet

52、heright.Forinstance,therearetypicallysomeobjectsallocatedatinitializationthatliveuntiltheprocessexits.Betweenthesetwoextremesareobjectsthatliveforthedurationofsomeintermediatecomputation,seenhereasthelumptotherightoftheinfantmortalitypeak.Someapplicationshaveverydifferentlookingdistributions,butasur

53、prisinglylargenumberpossessthisgeneralshape.Efficientcollectionismadepossiblebyfocusingonthefactthatamajorityofobjectsdieyoung.Todothis,memoryismanagedingenerations:memorypoolsholdingobjectsofdifferentages.Garbagecollectionoccursineachgenerationwhenitfillsup;thesecollectionsarerepresentedonthediagra

54、mabovewithverticalbars.Objectsareallocatedineden,andbecauseofinfantmortalitymostobjectsdiethere.WhenEdenfillsupitcausesaminorcollection,inwhichsomesurvivingobjectsaremovedtoanoldergeneration.Whenoldergenerationsneedtobecollectedthereisamajorcollectionthatisoftenmuchslowerbecauseitinvolvesalllivingob

55、jects.Thediagramshowsawell-tunedsysteminwhichmostobjectsdiebeforetheysurvivetothefirstgarbagecollection.Thelongeranobjectsurvives,themorecollectionsitwillendureandtheslowerGCbecomes.Byarrangingformostobjectstosurvivelessthanonecollection,garbagecollectioncanbeveryefficient.Thishappysituationcanbeups

56、etbyapplicationswithunusuallifetimedistributions,orbypoorlysizedgenerationsthatcausecollectionstobetoofrequent.Thedefaultgarbagecollectionparametersweredesignedtobeeffectiveformostsmallapplications.Theyarentoptimalformanyserverapplications.Thisleadstothecentraltenetofthisdocument:IfGChasbecomeabottl

57、eneck,youmaywishtocustomizethegenerationsizes.ChecktheverboseGCoutput,andthenexplorethesensitivityofyourindividualperformancemetrictotheGCparameters.TypesofcollectionEachgenerationhasanassociatedtypeofgarbagecollectionthatcanbeconfiguredtomakedifferentalgorithmictime,spaceandpausetradeoffs.In1.3,the

58、JVMimplementsthreeverydifferentgarbagecollectors:Copying(sometimescalledscavenge):thiscollectorveryefficientlymovesobjectsbetweentwoormoregenerations.Thesourcegenerationsareleftempty,allowingremainingdeadobjectstobereclaimedquickly.However,sinceitrequiresemptyspacetooperate,copyingrequiresmorefootpr

59、int.In1.3.1copyingcollectionisusedforallminorcollections.Mark-compact:thiscollectorallowsgenerationstobecollectedinplacewithoutreservingextramemory;however,compactionissignificantlyslowerthancopying.In1.3.1mark-compactisusedformajorcollections.Incremental(sometimescalledtrain):thiscollectorisusedonl

60、yif-Xincgcispassedonthecommandline.Bycarefulbookkeeping,incrementalGCcollectsjustaportionoftheoldgenerationatatime,tryingtospreadthelargepauseofamajorcollectionovermanyminorcollections.However,itisevenslowerthanmark-compactwhenconsideringoverallthroughput.Sincecopyingisveryfast,atuninggoalistocollec

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论