//关闭线程池 pool.shutdown(); try { // awaitTermination返回false即超时会继续循环,返回true即线程池中的线程执行完成主线程跳出循环往下执行,每隔10秒循环一次 while (!pool.awaitTermination(10, TimeUnit.SECONDS)); } catch (InterruptedException e) { e.PRintStackTrace(); } 在线程池关闭之后,该方法会一直进行检查直到所有的线程池中的线程都执行完毕才会继续主线程,从而实现我们的要求。 将表之间进行拆分之后,第二步就是将每张表的数据进行查询并进行处理之后再写入文件。但是单张表的数据也太大了,开始我们循环rs.next();。将没次查询到的数据写入TXT并记录数据的大小,重而拆分写多个不同的文件。但是这个还是太慢了,因为所有的数据处理都是串行的太慢了。 随后我们又做了,将所有数据封装了一个LIST并将返回的LIST拆分成十个小LIST写成多线程的方式进行处理,巴特,还是太年轻了。多线程中开多线程,导致程序中有几百个进程在跑,并且将内存中的放入了几十亿的数据。很抱歉,在某家公司进行测试的时候,64G的内存处理一般就内存溢出了……。所以该方案也不行。 接下来,我们就在想有没有更高效的方法,不必将每张表的所以数据都复制进内存在进行处理。而是将按多少条进行查询处理。一个是手工分页查询进行处理。一个是加序列进行处理。还有就是cachedrowset的方法。3.cachedrowset的使用
cachedrowset继承自ResultSet,它是将数据库的数据一次拷贝到内存中,并支持分页拷贝。在发现这个方案的时候才知道原来每次while(rs.next())都是与数据库的链接光标取下一行,原来自己的认知是将所有都加载到内存,看来还是自己太年轻了。cachedrowset是将数据复制到内存,它提供了一个分页方法setPageSize(size); 可以设置每页读取的数据数量并加载到内存,同理while(crs.nextpage()) 是取下一页。所以,我们将数据的逻辑放到了while里,不能直接将crs传入到多线程里进行处理,不然在进行字段数据获取的时候会报错。cachedrowset.createCopy()这个方法可以帮我们复制一份这个对象。我们可以将这个对象传入到线程池中进行处理。哈哈,到这里是不是以为已经可以了。答案是否定的%>_<% 在实际测试的时候发现,每次还是将数据全部复制到了内存。虽然线程池的线程个数有设置,但是循环每次crs.nextpage()会将复制后的对象放进内存中在放入线程池的队列中……。所以我们要在循环取数的时候判断线程池是否有空闲的在用crs.nextpage()取下一页的数据。这样就不会讲一个表的所有数据加载到内存了。这样内存中的数据量等于=线程数*每页数量+每页数量。这样就可以有效的将问题分解处理了。执行将数据查询和业务逻辑耦合了……4.总结
通过这次问题的分析以及初步解决。感觉自己知道的东西还是有限。无论是自己的眼界和见解都还没用达到一个程序员应有的水平,对于不常用的东西还是知识储备不足。哦对了,cachedrowset的Statement要是可滚动的。欢迎各位可以有更好的方案,同时也随便告诉下我这个无知的萌新。
新闻热点
疑难解答