本节会从软件开发功能需求的角度引出 的功能,然后我们会自己实现这个功能,最后再分析JUC Executors 的源码。
Doug Lea < Java Concurrcy In Practice > 第六章 任务执行 中描述:
大多数的应用程序是围绕 进行组织的。任务就是抽象的、独立的工作单元。把应用程序的工作分离为一个个的任务,可以简化应用程序(分而治之的思想)。
服务器应用程序应该具有:
1、良好的吞吐量和快速的响应能力;
2、在负载越来越大时,性能会平缓的下降,而不是直接导致简单粗暴的;
一个线程串行执行任务 和 每个任务开启一个线程都存在一些问题。
一个线程串行执行任务的问题:应用程序吞吐量和相应能力都很差。
每个任务开启一个线程执行(thread-per-task)的问题:
1、应用程序需求
功能需求:服务器应用程序会不断接收客户端的请求,收到请求后,应用程序对请求进行处理。
非功能需求:支撑高并发和高可用
2、应用程序设计
根据功能需求的描述,我们抽出几个名词和动词:
名词:服务器应用程序;客户端的请求;
动词:接收请求;对请求进行处理;
伪代码:
上面的实现是最直接的实现方式,但我们在写程序的时候还要考虑程序的给功能需求。
根据文章开头描述,我们不能使用上面的这种实现方式,这种是第一种串行的执行方式。
采取第二种方式,伪代码如下:
第二中方式也是存在问题的
我们采用线程池的方式 ,伪代码如下:
上面的伪代码需要进一步细化:
1、需要将请求(任务)和线程进行绑定,这样才能将任务分配给线程
2、大部分的情况下,任务是比线程数多的,所以我们需要一个地方来暂存任务请求,然后空闲的线程从这个地方来取出任务进行执行
我们尝试实现一下:
上面的伪代码,还有需要很多细节和设计上的问题需要解决:
1、Request 是自己定义的类,其实应该是一个客户端实现的接口,只有一个execute方法,作为一个Java 开发人员我们思考一下Java提供的API里面有这样的接口么很明显 接口便是。
2、我们的需要实现的线程池逻辑和业务有关系么不是可以独立出来做成通用的功能类/p>
3、WorkerThread 的run方法是不是应该循环从queue中取出任务执行/p>
上面就是我们设计的过程,到这步我们发现要考虑很多实现上的细节了,所以我们从现在开始该进行编码了,并在编码的过程中不断的进行重构。
在实现代码前我们想想线程池的命名:线程池的作用是用来执行任务,所以我们将其命名为
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!