国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

關(guān)于cachedrowset在實(shí)際項(xiàng)目中的應(yīng)用

2019-11-06 06:43:13
字體:
供稿:網(wǎng)友

1.問題的產(chǎn)生原因

    由于項(xiàng)目需求原因,需要實(shí)現(xiàn)一個(gè)功能就是,抽取大量的數(shù)據(jù)庫數(shù)據(jù)然后寫入文本并打包上傳。看似一個(gè)很簡單的東西,在大數(shù)據(jù)量的環(huán)境下就顯得不是那么簡單了。首先有60張左右的表需要進(jìn)行數(shù)據(jù)的處理。各個(gè)公司情況不同,表的總數(shù)據(jù)量可能是幾千萬到幾十億不等。所以,耗時(shí)非常嚴(yán)重。

2.問題解決過程

    由于只是單純的進(jìn)行數(shù)據(jù)的提取加工寫入文本打包等操作,不涉及表與表之間的業(yè)務(wù)邏輯。那么,大家下意識(shí)的的想到的就是多線程了。同樣,我們也是用多線程進(jìn)行第一步的數(shù)據(jù)處理。在這第一步就遇到了一個(gè)小坑,沒有用線程池進(jìn)行處理。并且業(yè)務(wù)邏輯方面也要做到主線程在等待所有子線程處理完畢之后在進(jìn)行處理。線程有個(gè)方法就是join()方法,單純的以為將所有的線程的join()方法連到一起就可以做到主線程等待所有子線程處理完畢之后再進(jìn)行處理。巴特,還是太年輕在測(cè)試的時(shí)候就發(fā)現(xiàn),這種方法做不到我們要求的效果。在經(jīng)過查詢搜集資料之后發(fā)現(xiàn)ExecutorService pool=Executors.newFixedThreadPool(threadNumber);一個(gè)固定線程池?cái)?shù)量的線程池可以實(shí)現(xiàn)我們的要求。
//關(guān)閉線程池			pool.shutdown();			 try  			 {  			 // awaitTermination返回false即超時(shí)會(huì)繼續(xù)循環(huán),返回true即線程池中的線程執(zhí)行完成主線程跳出循環(huán)往下執(zhí)行,每隔10秒循環(huán)一次  			 while (!pool.awaitTermination(10, TimeUnit.SECONDS));  			 }  			 catch (InterruptedException e)  			 {  			 e.PRintStackTrace();  			 }  在線程池關(guān)閉之后,該方法會(huì)一直進(jìn)行檢查直到所有的線程池中的線程都執(zhí)行完畢才會(huì)繼續(xù)主線程,從而實(shí)現(xiàn)我們的要求。     將表之間進(jìn)行拆分之后,第二步就是將每張表的數(shù)據(jù)進(jìn)行查詢并進(jìn)行處理之后再寫入文件。但是單張表的數(shù)據(jù)也太大了,開始我們循環(huán)rs.next();。將沒次查詢到的數(shù)據(jù)寫入TXT并記錄數(shù)據(jù)的大小,重而拆分寫多個(gè)不同的文件。但是這個(gè)還是太慢了,因?yàn)樗械臄?shù)據(jù)處理都是串行的太慢了。    隨后我們又做了,將所有數(shù)據(jù)封裝了一個(gè)LIST并將返回的LIST拆分成十個(gè)小LIST寫成多線程的方式進(jìn)行處理,巴特,還是太年輕了。多線程中開多線程,導(dǎo)致程序中有幾百個(gè)進(jìn)程在跑,并且將內(nèi)存中的放入了幾十億的數(shù)據(jù)。很抱歉,在某家公司進(jìn)行測(cè)試的時(shí)候,64G的內(nèi)存處理一般就內(nèi)存溢出了……。所以該方案也不行。    接下來,我們就在想有沒有更高效的方法,不必將每張表的所以數(shù)據(jù)都復(fù)制進(jìn)內(nèi)存在進(jìn)行處理。而是將按多少條進(jìn)行查詢處理。一個(gè)是手工分頁查詢進(jìn)行處理。一個(gè)是加序列進(jìn)行處理。還有就是cachedrowset的方法。

3.cachedrowset的使用

    cachedrowset繼承自ResultSet,它是將數(shù)據(jù)庫的數(shù)據(jù)一次拷貝到內(nèi)存中,并支持分頁拷貝。在發(fā)現(xiàn)這個(gè)方案的時(shí)候才知道原來每次while(rs.next())都是與數(shù)據(jù)庫的鏈接光標(biāo)取下一行,原來自己的認(rèn)知是將所有都加載到內(nèi)存,看來還是自己太年輕了。cachedrowset是將數(shù)據(jù)復(fù)制到內(nèi)存,它提供了一個(gè)分頁方法setPageSize(size); 可以設(shè)置每頁讀取的數(shù)據(jù)數(shù)量并加載到內(nèi)存,同理while(crs.nextpage()) 是取下一頁。所以,我們將數(shù)據(jù)的邏輯放到了while里,不能直接將crs傳入到多線程里進(jìn)行處理,不然在進(jìn)行字段數(shù)據(jù)獲取的時(shí)候會(huì)報(bào)錯(cuò)。cachedrowset.createCopy()這個(gè)方法可以幫我們復(fù)制一份這個(gè)對(duì)象。我們可以將這個(gè)對(duì)象傳入到線程池中進(jìn)行處理。哈哈,到這里是不是以為已經(jīng)可以了。答案是否定的%>_<%    在實(shí)際測(cè)試的時(shí)候發(fā)現(xiàn),每次還是將數(shù)據(jù)全部復(fù)制到了內(nèi)存。雖然線程池的線程個(gè)數(shù)有設(shè)置,但是循環(huán)每次crs.nextpage()會(huì)將復(fù)制后的對(duì)象放進(jìn)內(nèi)存中在放入線程池的隊(duì)列中……。所以我們要在循環(huán)取數(shù)的時(shí)候判斷線程池是否有空閑的在用crs.nextpage()取下一頁的數(shù)據(jù)。這樣就不會(huì)講一個(gè)表的所有數(shù)據(jù)加載到內(nèi)存了。這樣內(nèi)存中的數(shù)據(jù)量等于=線程數(shù)*每頁數(shù)量+每頁數(shù)量。這樣就可以有效的將問題分解處理了。執(zhí)行將數(shù)據(jù)查詢和業(yè)務(wù)邏輯耦合了……

4.總結(jié)

通過這次問題的分析以及初步解決。感覺自己知道的東西還是有限。無論是自己的眼界和見解都還沒用達(dá)到一個(gè)程序員應(yīng)有的水平,對(duì)于不常用的東西還是知識(shí)儲(chǔ)備不足。哦對(duì)了,cachedrowset的Statement要是可滾動(dòng)的。歡迎各位可以有更好的方案,同時(shí)也隨便告訴下我這個(gè)無知的萌新。

    
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 康乐县| 南京市| 甘谷县| 嘉荫县| 宁乡县| 平湖市| 固阳县| 新密市| 崇左市| 宜宾县| 炉霍县| 普格县| 广元市| 富平县| 嘉黎县| 苍梧县| 利辛县| 英吉沙县| 元朗区| 桂平市| 府谷县| 七台河市| 纳雍县| 定西市| 弋阳县| 平舆县| 营山县| 抚松县| 龙游县| 兰溪市| 西吉县| 焉耆| 封丘县| 信宜市| 资兴市| 基隆市| 讷河市| 通许县| 北安市| 根河市| 孟村|