网站建设OA系统开发,品牌设计的概念,河北石家庄,海外营销推广我不久前参与了一个项目#xff0c;该项目的报告流程如下#xff1a; 用户会要求举报 报告要求将被翻译成较小的部分 每个零件的报告将基于零件/节的类型由报告生成器生成 组成报告的各个部分将重新组合成最终报告#xff0c;并返回给用户 我的目标是展示如何从错误的实… 我不久前参与了一个项目该项目的报告流程如下 用户会要求举报 报告要求将被翻译成较小的部分 每个零件的报告将基于零件/节的类型由报告生成器生成 组成报告的各个部分将重新组合成最终报告并返回给用户 我的目标是展示如何从错误的实施过渡到相当好的实施 单元测试最好地展示了我拥有的一些基本构建基块这是一个测试助手它生成示例报告请求其中包括组成报告请求部分 public class FixtureGenerator {public static ReportRequest generateReportRequest(){ListReportRequestPart requestParts new ArrayListReportRequestPart();MapString, String attributes new HashMapString, String();attributes.put(user,user);Context context new Context(attributes );ReportRequestPart part1 new ReportRequestPart(Section.HEADER, context);ReportRequestPart part2 new ReportRequestPart(Section.SECTION1, context);ReportRequestPart part3 new ReportRequestPart(Section.SECTION2, context);ReportRequestPart part4 new ReportRequestPart(Section.SECTION3, context);ReportRequestPart part5 new ReportRequestPart(Section.FOOTER, context); requestParts.add(part1); requestParts.add(part2);requestParts.add(part3);requestParts.add(part4);requestParts.add(part5);ReportRequest reportRequest new ReportRequest(requestParts );return reportRequest;}} 以及生成报告的测试 public class FixtureGenerator {Testpublic void testSequentialReportGeneratorTime(){long startTime System.currentTimeMillis();Report report this.reportGenerator.generateReport(FixtureGenerator.generateReportRequest());long timeForReport System.currentTimeMillis()-startTime;assertThat(report.getSectionReports().size(), is (5));logger.error(String.format(Sequential Report Generator : %s ms, timeForReport));} 生成报告一部分的组件是一个虚拟实现具有2秒的延迟以模拟IO密集调用 public class DummyReportPartGenerator implements ReportPartGenerator{Overridepublic ReportPart generateReportPart(ReportRequestPart reportRequestPart) {try {//Deliberately introduce a delayThread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return new ReportPart(reportRequestPart.getSection(), Report for reportRequestPart.getSection());}
} 顺序执行 给定这些基本的类集我的第一个天真的顺序实现如下 public class SequentialReportGenerator implements ReportGenerator {private ReportPartGenerator reportPartGenerator;Overridepublic Report generateReport(ReportRequest reportRequest){ListReportRequestPart reportRequestParts reportRequest.getRequestParts();ListReportPart reportSections new ArrayListReportPart();for (ReportRequestPart reportRequestPart: reportRequestParts){reportSections.add(reportPartGenerator.generateReportPart(reportRequestPart));}return new Report(reportSections);}......
} 显然对于其中包含5个部分的报告请求每个部分需要2秒钟才能完成此报告大约需要10秒钟才能返回给用户。 它请求同时进行。 基于原始线程的实现 以下是第一个并发实现虽然不好但比顺序的要好其后是为每个报告请求部分生成一个线程等待要生成的报告部分使用thread.join方法并在出现这些块时对其进行汇总在。 public class RawThreadBasedReportGenerator implements ReportGenerator {private static final Logger logger LoggerFactory.getLogger(RawThreadBasedReportGenerator.class);private ReportPartGenerator reportPartGenerator;Overridepublic Report generateReport(ReportRequest reportRequest) {ListReportRequestPart reportRequestParts reportRequest.getRequestParts();ListThread threads new ArrayListThread();ListReportPartRequestRunnable runnablesList new ArrayListReportPartRequestRunnable();for (ReportRequestPart reportRequestPart : reportRequestParts) {ReportPartRequestRunnable reportPartRequestRunnable new ReportPartRequestRunnable(reportRequestPart, reportPartGenerator);runnablesList.add(reportPartRequestRunnable);Thread thread new Thread(reportPartRequestRunnable);threads.add(thread);thread.start();}for (Thread thread : threads) {try {thread.join();} catch (InterruptedException e) {logger.error(e.getMessage(), e);}}ListReportPart reportParts new ArrayListReportPart();for (ReportPartRequestRunnable reportPartRequestRunnable : runnablesList) {reportParts.add(reportPartRequestRunnable.getReportPart());}return new Report(reportParts);} .....
} 这种方法的危险在于将为每个报表部件创建一个新线程因此在实际情况下如果同时发出100个请求并且每个请求都产生5个线程则可能最终在vm中创建500个代价高昂的线程!! 因此必须以某种方式限制线程的创建。 在下一篇博客文章中我将介绍另外两种控制线程的方法。 参考 并发–来自JCG合作伙伴 Biju Kunjummen的all和杂物博客 并发-顺序和原始线程 。 翻译自: https://www.javacodegeeks.com/2012/07/concurrency-sequential-and-raw-thread.html