任务执行策略

 菜小川

转载请注明原创出处,谢谢!


任务执行策略_第1张图片

大多数并发应用程序都是围绕任务执行来设计的,设计时需要找出清晰的任务边界。大多数服务器应用程序都以独立的客户请求为边界。独立的客户请求作为任务边界,可以实现任务的独立性

串行地执行任务

应用程序可以通过多种策略调度任务,最简单的策略就是在单个线程中串行地执行各项任务。下图程序中的SingleThreadWebServer将串行地处理任务(即通过80端口接收http请求)。

任务执行策略_第2张图片

问题分析:

SingleThreadWebServer很简单,理论上也是正确的,但在实际生产环境中性能却很糟糕。因为每次只能处理一个请求,当服务器正在处理请求时,新来的请求必须等待现有请求执行完成,然后服务器才能再次调用accept。如果处理请求的速度很快并且handlerRequest可以立即返回,那么这种是可行的,但实际生产中不可能如此简单,尤其是单线程服务器在处理文件I/O或数据库请求等阻塞操作时,如果请求阻塞时间过长,服务器将失去响应,导致服务器资源利用率(因为阻塞操作时,CPU处于空闲状态)极低。

并发地执行任务

下图程序中的ThreadPerTaskWebServer将通过为每个请求创建一个线程提供服务。

任务执行策略_第3张图片

设计好处:

1、任务处理过程从主线程中分离出来,使得主循环能够快速地重新等待下一个到来的连接,这使程序在完成前面的请求之前可以接受新的请求,从而提高响应性。

2、任务可以同时服务多个请求,如果有多个处理器或任务再遇到阻塞操作(I/O、获取锁等),程序的吞吐量将提高。

问题分析:

在正常的负载情况下,为每个任务分配一个线程这种策略能提升性能,只要请求到达速率不超出服务器的请求能力,这种策略可以同时带来更快的响应性和更高的吞吐率。然而,在生产环境中,这种策略存在缺陷,它没有限制可创建线程的数量,只限制了远程用户提交http请求的速率。

1、线程的生命周期开销非常高。线程的创建与销毁需要代价,因为线程的创建过程需要时间,延迟处理的请求,并且需要JVM和操作系统提供一些辅助操作。

2、资源消耗。活跃的线程会消耗系统资源,尤其是内存。如果可运行的线程数量多于可用处理器的数量,那么有些线程将闲置。大量空闲的线程会占用大量内存,给垃圾回收器带来压力,而且大量线程在竞争CPU资源时还将产生其他的性能开销。

3、稳定性。不同的平台在可创建线程的数量上存在限制(JVM启动参数、Thread构造函数中请求的栈大小、底层操作系统对线程限制等),如果破坏限制,很有可能出现OutOfMemoryError异常

更好的设计策略将在后期文章中分享。


微信公众号

任务执行策略_第4张图片

你可能感兴趣的:(任务执行策略)