【总结】ITOO在线考试性能优化——多线程(二)
业务逻辑:
抽卷的时候我们的逻辑是做成抽卷的过程中并且插入答案到答题记录并且更新学生状态。
代码逻辑:
ListeningExecutorService executorService =MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); final ListenableFuture<Integer>listenableFuture = executorService.submit(new Callable<Integer>() { @Override public Integer call() throws Exception{ System.out.println("调用插入方法"); TimeUnit.SECONDS.sleep(1); return 7; } }); Futures.addCallback(listenableFuture, newFutureCallback<Integer>() { @Override public void onSuccess(Integer result){ System.out.println("修改更新状态" +result); } @Override public void onFailure(Throwable t) { t.printStackTrace(); } });
代码的感受:
- jdk5之后有了Future这种异步执行的结构,之前在之前的在线编辑里面也是用过的,以future这种数据结构作为类型,尤其是对于callable这种又返回结果的线程任何是完美的搭配。ListenableFuture无疑是对于future的扩展。
对比的代码:
ExecutorService executorService = Executors.newCachedThreadPool(); List<Future<PaperDetail>> resultList = new ArrayList<Future<PaperDetail>>(); for (PaperDetail returnSinglePaperDetail : returnPaperDetail) { Future<PaperDetail> future = executorService.submit(new myCallable(returnSinglePaperDetail)); resultList.add(future); } List<PaperDetail> listPapaerDeatil=new ArrayList<PaperDetail>(); //遍历任务的结果 for (Future<PaperDetail> fp: resultList) { try { PaperDetail enPaperDetail =fp.get(); listPapaerDeatil.add(enPaperDetail); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } executorService.shutdown(); }
现在看一下这段代码问题真的很多,虽然,future可以通过get方法来获取任务执行结果,因为我明明可以通过isdone这些方法来判断线程是否执行完的。平时如果我们要知道Future表示一个异步计算任务,当任务完成时可以得到计算结果。如果我们希望一旦计算完成就拿到结果展示给用户或者做另外的计算,就必须使用另一个线程不断的查询计算状态。这样做,代码复杂,而且效率低下。使用ListenableFuture帮我们检测Future是否完成了,如果完成就自动调用回调函数,这样可以减少并发程序的复杂度。
完整代码如下:
public class callUpdate implements FutureCallback<Integer>{ private String ExamDataBaseAuthority; private String examArragementIDString; private ShardedJedis jedis; private ReconstructGetPaperBean reconstructGetPaperBean; private String ExamState; public callUpdate(String ExamDataBaseAuthority, String examArragementIDString,ShardedJedis jedis,ReconstructGetPaperBean reconstructGetPaperBean,String ExamState) { this.examArragementIDString=examArragementIDString; this.ExamDataBaseAuthority=ExamDataBaseAuthority; this.jedis=jedis; this.reconstructGetPaperBean=reconstructGetPaperBean; this.ExamState=ExamState; } @Override public void onFailure(Throwable arg0) { System.out.println("更新失败状态"); } @Override public void onSuccess(Integer result) { boolean state = reconstructGetPaperBean.updateStudentState(ExamConstants.EXAMING, ExamDataBaseAuthority, examArragementIDString); if (state==true) { //6.修改redis里面的ExamState的状态 jedis.set(ExamState, ExamConstants.EXAMING); jedis.expire(ExamState, 7200); } System.out.println("更新状态成功"); } }
public class insertAndUpdateState implements Callable<Integer>{ private ReconstructGetPaperBean reconstructGetPaperBean; private ExamineeArrangement studentInfo; private ShardedJedis jedis; private List<PaperDetail> paperDetails; private List<QuestionMain> questionMains; private String ExamDataBaseAuthority; public insertAndUpdateState(ExamineeArrangement studentInfo,ShardedJedis jedis, List<PaperDetail> paperDetails,List<QuestionMain> questionMains,String ExamDataBaseAuthority,ReconstructGetPaperBean reconstructGetPaperBean) { this.studentInfo=studentInfo; this.jedis=jedis; this.paperDetails=paperDetails; this.questionMains=questionMains; this.ExamDataBaseAuthority=ExamDataBaseAuthority; this.reconstructGetPaperBean=reconstructGetPaperBean; } @Override public Integer call() throws Exception { boolean flag = update(questionMains,paperDetails,ExamDataBaseAuthority,studentInfo); if (flag) { return 0; }else{ return 1; } } /** * 插入学生学生试卷 * */ private boolean update(List<QuestionMain>questionMains,List<PaperDetail>paperDetails,String databaseName,ExamineeArrangement studentInfo){ …… }
总结:
现阶段能理解的程度只能到这里,还有很多东西需要查找,看了api发现里面底层用的委托,知道监听是怎么实现的了。话说好难……从第一次写那篇线程到现在第二篇,隔了好几个月了,佩服写系列博客的人……