国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

POI用戶(hù)模型的重構(gòu)與優(yōu)化

2019-10-08 06:43吉豪杰宋欣潮
軟件 2019年5期
關(guān)鍵詞:設(shè)計(jì)模式

吉豪杰 宋欣潮

摘 ?要: Apache POI中的用戶(hù)模型是目前用于處理Excel數(shù)據(jù)的最為廣泛的應(yīng)用技術(shù),但用戶(hù)模型存在許多明顯的弊端。本文將以一個(gè)學(xué)生檔案管理系統(tǒng)為例,對(duì)用戶(hù)模型中存在的問(wèn)題以及產(chǎn)生問(wèn)題的原因進(jìn)行分析,并針對(duì)這些問(wèn)題,借用面向過(guò)程的設(shè)計(jì)思想對(duì)用戶(hù)模型進(jìn)行優(yōu)化和改進(jìn)。使用不同規(guī)模的數(shù)據(jù)量對(duì)改進(jìn)前后的用戶(hù)模型進(jìn)行測(cè)試,并對(duì)測(cè)試結(jié)果進(jìn)行比較和分析,最終在一定程度上解決了用戶(hù)模型的弊端,提升了用戶(hù)模型的性能。

關(guān)鍵詞: 用戶(hù)模型;生產(chǎn)者消費(fèi)者模型;POI技術(shù);數(shù)據(jù)優(yōu)化;內(nèi)存溢出;設(shè)計(jì)模式;java多線(xiàn)程

中圖分類(lèi)號(hào): TP315 ? ?文獻(xiàn)標(biāo)識(shí)碼: A ? ?DOI:10.3969/j.issn.1003-6970.2019.05.038

本文著錄格式:吉豪杰,宋欣潮. POI用戶(hù)模型的重構(gòu)與優(yōu)化[J]. 軟件,2019,40(5):193199

【Abstract】: The UserModel in Apache POI is the most widely used technology for processing Excel data at present, but the user model has many obvious disadvantages.This paper will take a student file management system as an example to analyze the problems existing in the UserModel and the causes of the problems. In view of these problems, the UserModel will be optimized and improved by using the process-oriented design idea.The data volumes of different scales were used to test the UserModel before and after the improvement, and the test results were compared and analyzed. Finally, the disadvantages of the UserModel were solved to some extent, and the performance of the UserModel was improved.

【Key words】: UserModel; Producer consumer model; POI; Data optimization; Out of memoryerror; Design mode; Java multithreading

0 ?引言

在當(dāng)前的軟件開(kāi)發(fā)中,越來(lái)越多的需求涉及到對(duì)MicroSoft Office文檔的處理,其中對(duì)Excel數(shù)據(jù)文檔的處理尤為普遍。因此,關(guān)于對(duì)Excel文件處理的討論與研究也愈演愈烈。到目前為止,已經(jīng)出現(xiàn)了許多關(guān)于處理Excel文件的技術(shù)和開(kāi)源項(xiàng)目,例如Java Excel Api(jxl),Apache POI[1],Alibaba EasyExcel等。這些開(kāi)源項(xiàng)目各有特色,都能夠適用于不同的開(kāi)發(fā)場(chǎng)景,滿(mǎn)足了大多數(shù)不同的開(kāi)發(fā)需求,但也存在諸多問(wèn)題,其中對(duì)Apache POI相關(guān)技術(shù)所存在問(wèn)題的研究是本文討論的重點(diǎn)。本文的創(chuàng)新點(diǎn)在于將面向過(guò)程的生產(chǎn)者消費(fèi)者模型[2]的設(shè)計(jì)思想應(yīng)用到傳統(tǒng)的用戶(hù)模型當(dāng)中,以及采用多線(xiàn)程[3-9]的方式實(shí)現(xiàn)用戶(hù)模型,對(duì)傳統(tǒng)的用戶(hù)模型處理Excel數(shù)據(jù)的程序進(jìn)行重構(gòu),使用戶(hù)模型在程序結(jié)構(gòu)上邏輯更加清晰、功能更加明確,在數(shù)據(jù)處理能力上更加高效。

1 ?POI用戶(hù)模型

1.1 ?用戶(hù)模型簡(jiǎn)介

POI是由Apache組織提供的用java編寫(xiě)的免費(fèi)開(kāi)源的跨平臺(tái)的 Java API,Apache POI提供API給Java程序?qū)icroSoft office格式檔案讀和寫(xiě)的功 能[1]。POI中關(guān)于Excel數(shù)據(jù)處理的部分主要包括User API、Event API和Streaming UserModel API。本文將重點(diǎn)討論User API中的UserModel。

所謂的UserModel實(shí)際上就是基于Dom方式的解析,Dom解析就是將文件全部讀入內(nèi)存,對(duì)文件內(nèi)部的結(jié)構(gòu)進(jìn)行建模,形成一顆Dom樹(shù)的過(guò)程,如圖1用戶(hù)模型的Dom樹(shù)結(jié)構(gòu)。

從圖1中可以看出,用戶(hù)模型提供封裝好的Workbook、Sheet、Row、Cell等實(shí)例來(lái)完成對(duì)excel數(shù)據(jù)的讀寫(xiě)。

1.2 ?用戶(hù)模型的應(yīng)用

經(jīng)過(guò)對(duì)用戶(hù)模型的簡(jiǎn)單介紹,現(xiàn)在以文獻(xiàn)[4]中提到的學(xué)生檔案管理系統(tǒng)為例,對(duì)用戶(hù)模型的Excel數(shù)據(jù)解析功能進(jìn)行實(shí)現(xiàn)。該功能的業(yè)務(wù)處理過(guò)程為:①以流的方式接受excel文件;②根據(jù)接受的文件生成WorkBook對(duì)象;③根據(jù)Dom結(jié)構(gòu),遍歷每個(gè)Sheet的每一個(gè)Row,將每一個(gè)Row中的Cell的值讀取出來(lái),存放到list集合中;④對(duì)list中的數(shù)據(jù)進(jìn)行類(lèi)型轉(zhuǎn)換,并封裝到領(lǐng)域?qū)ο骃tudent中,生成存放Student對(duì)象的集合;⑤利用數(shù)據(jù)庫(kù)的批量添加操作,將Student集合持久化到數(shù)據(jù)庫(kù)中(涉及到多表操作)。

用戶(hù)模型代碼:

Student類(lèi):

public class Student {

private BigInteger stuId;//學(xué)號(hào)

private Archive archive;//檔案

private Profession pro;//專(zhuān)業(yè)

private Department department;//院系

private String stuName;//姓名

private String stuSex;//性別

private String stuSendnum;//派遣證號(hào)

private String stuClass;//班級(jí)

private String stuLocation;//生源地

//省略部分屬性和set、get方法

}

用戶(hù)模型解析excel方法:

public static List> getListByExcel(InputStream in,String fileName) throws Exception{

List> list=null;

Workbook wb=getWorkBook(in,fileName); //獲取WorkBook對(duì)象

if (wb!=null){

Sheet sheet=null;

Row row=null;

Cell cell=null;

list=new ArrayList>();

for (int i=0;i

sheet=wb.getSheetAt(i);

if (sheet==null){continue;}

//遍歷每一行

for (int j=sheet.getFirstRowNum(); j<=sheet.getLastRowNum();j++){

row=sheet.getRow(j);

Integer columns= (int)row. getLastCellNum();

//遍歷每一列

List rowData=new ArrayList<>();

for (int m=0;m

cell=row.getCell(m);

if (cell!=null) {

rowData.add (getCellValue(cell));//數(shù)據(jù)類(lèi)型轉(zhuǎn)換

}else{

rowData.add("");

}

}

//將每一行的數(shù)據(jù)放到list中

list.add(rowData);

}

}

}

return list;

}

業(yè)務(wù)邏輯方法:

public boolean uploadExcel(InputStream in, MultipartFile file) {

//獲取數(shù)據(jù)源

List> rowList=getListByExcel(in,file.getName());

//數(shù)據(jù)源封裝成業(yè)務(wù)對(duì)象Student,存放到studentList中

//調(diào)用dao層的數(shù)據(jù)庫(kù)操作方法,批量添加Student對(duì)象

//添加成功返回true,否則返回false

}

1.3 ?用戶(hù)模型的缺陷及原因分析

采用用戶(hù)模型的方式讀寫(xiě)Excel文件,由于這種方式容易理解,操作也較簡(jiǎn)單,所以成為了開(kāi)發(fā)人員最常用的方式。但是這種方式也存在很明顯的弊端:因?yàn)樵摲绞绞腔贒om內(nèi)存解析的,所以對(duì)系統(tǒng)內(nèi)存的依賴(lài)也就比較嚴(yán)重。也就是說(shuō),WorkBook對(duì)象是將整個(gè)文件流緩沖到系統(tǒng)內(nèi)存當(dāng)中,使用用戶(hù)模型處理數(shù)據(jù)就要求系統(tǒng)有足夠的內(nèi)存空間去容納以WorkBook對(duì)象為根的Dom結(jié)構(gòu)。

在1.2的代碼中可以看出,系統(tǒng)不僅會(huì)為WorkBook對(duì)象分配內(nèi)存,而且還會(huì)為封轉(zhuǎn)的Student對(duì)象集合分配大量空間。當(dāng)數(shù)據(jù)量逐漸增大,對(duì)系統(tǒng)內(nèi)存和cpu的開(kāi)銷(xiāo)也隨之增大,直到系統(tǒng)沒(méi)有足夠的內(nèi)存去處理數(shù)據(jù)時(shí),就會(huì)造成內(nèi)存溢出,導(dǎo)致數(shù)據(jù)處理失敗。

以學(xué)生檔案管理系統(tǒng)為例,對(duì)用戶(hù)模型的系統(tǒng)資源使用情況進(jìn)行分析。如圖2數(shù)據(jù)量為1w時(shí)系統(tǒng)內(nèi)存使用情況。

從圖2中有上下兩條曲線(xiàn),上方曲線(xiàn)表示堆空間的最大值,下方曲線(xiàn)表示當(dāng)前程序已經(jīng)占用的空間。當(dāng)有1萬(wàn)條excel數(shù)據(jù)時(shí),系統(tǒng)會(huì)在一定時(shí)間內(nèi)對(duì)這些數(shù)據(jù)分配內(nèi)存并處理,占用內(nèi)存大小大約60M,處理完數(shù)據(jù)后,立即釋放空間。對(duì)于1萬(wàn)數(shù)據(jù)所占用的內(nèi)存,系統(tǒng)完全有能力分配,所以不會(huì)造成內(nèi)存溢出的情況。

如圖3數(shù)據(jù)量為10w時(shí)系統(tǒng)內(nèi)存使用情況。

由圖3可知,當(dāng)數(shù)據(jù)量增加到10萬(wàn)時(shí),系統(tǒng)內(nèi)存占用空間從100M迅速增加到700M以上并且呈緩慢上升的趨勢(shì)。系統(tǒng)的堆空間也逐漸擴(kuò)容到最大值,無(wú)法繼續(xù)擴(kuò)大,系統(tǒng)的可用內(nèi)存資源迅速減少,直到系統(tǒng)沒(méi)有足夠的內(nèi)存空間時(shí),拋出內(nèi)存溢出異常,此時(shí)10w條數(shù)據(jù)添加到數(shù)據(jù)庫(kù)失敗。

內(nèi)存占用空間迅速增加是因?yàn)樯闪嘶贒om結(jié)構(gòu)的WorkBook對(duì)象,呈緩慢上升趨勢(shì)是因?yàn)橄到y(tǒng)在不斷生成Student對(duì)象。 正是因?yàn)閃orkBook對(duì)象和不斷生成的Student對(duì)象,才造成了系統(tǒng)內(nèi)存溢出。

雖然目前已經(jīng)有很多方法可以替代用戶(hù)模型去完成大數(shù)據(jù)量的Excel數(shù)據(jù)解析功能,比如POI中的基于事件驅(qū)動(dòng)的事件模型和基于流式解析的流用戶(hù)模型、基于xml的excel數(shù)據(jù)解析方式[7]等,但是對(duì)于用戶(hù)模型本身的缺陷還未能夠解決。解決用戶(hù)模型的內(nèi)存溢出問(wèn)題,主要從兩方面入手:一是減少WorkBook對(duì)象占用的內(nèi)存空間,另一個(gè)是優(yōu)化不斷生成的Student對(duì)象的存儲(chǔ)結(jié)構(gòu),本文將重點(diǎn)從后者入手來(lái)解決內(nèi)存溢出問(wèn)題。

2 ?生產(chǎn)者消費(fèi)者模型

2.1 ?介紹

生產(chǎn)者消費(fèi)者模型[2]是面向過(guò)程編程中的一種高效設(shè)計(jì)模式[8],該模型包括三種角色:生產(chǎn)者、消費(fèi)者、數(shù)據(jù)倉(cāng)庫(kù)。其中生產(chǎn)者負(fù)責(zé)獲取數(shù)據(jù)、數(shù)據(jù)類(lèi)型轉(zhuǎn)換等數(shù)據(jù)準(zhǔn)備過(guò)程,消費(fèi)者負(fù)責(zé)處理生產(chǎn)者準(zhǔn)備好的數(shù)據(jù),該模型通過(guò)一個(gè)數(shù)據(jù)倉(cāng)庫(kù)來(lái)實(shí)現(xiàn)生產(chǎn)者與消費(fèi)者的解耦,降低生產(chǎn)者與消費(fèi)者之間的依賴(lài)關(guān)系,并且支持并發(fā)、忙閑不均等情況的處理。如圖4生產(chǎn)者消費(fèi)者模型的工作原理。

2.2 ?應(yīng)用

通常,處理Excel數(shù)據(jù)的過(guò)程為:①通過(guò)文件流來(lái)獲取數(shù)據(jù)源,②根據(jù)具體的業(yè)務(wù)邏輯對(duì)數(shù)據(jù)源中的數(shù)據(jù)進(jìn)行封裝,③對(duì)封裝好的數(shù)據(jù)進(jìn)行相應(yīng)的業(yè)務(wù)處理。這樣的數(shù)據(jù)處理過(guò)程與生產(chǎn)者消費(fèi)者模型的工作原理非常相似,過(guò)程①和②可以通過(guò)生產(chǎn)者來(lái)完成,數(shù)據(jù)存儲(chǔ)可以通過(guò)數(shù)據(jù)倉(cāng)庫(kù)來(lái)完成,過(guò)程③可以用消費(fèi)者來(lái)實(shí)現(xiàn)。

數(shù)據(jù)倉(cāng)庫(kù)通過(guò)維持一個(gè)恒定大小的緩沖區(qū)域來(lái)保證系統(tǒng)的內(nèi)存消耗,可以有效解決內(nèi)存溢出問(wèn)題。由于生產(chǎn)者消費(fèi)者模型支持并發(fā),所以可以利用多線(xiàn)程的方式來(lái)高效率實(shí)現(xiàn)數(shù)據(jù)解析過(guò)程,充分利用cpu資源,達(dá)到提升系統(tǒng)性能的目的。通過(guò)對(duì)生產(chǎn)者消費(fèi)者模型的利用,讓數(shù)據(jù)解析過(guò)程的邏輯更加清晰,各部分分工明確,便于后期的系統(tǒng)維護(hù)和更改。

3 ?重構(gòu)用戶(hù)模型

3.1 ?利用生產(chǎn)者消費(fèi)者模型改進(jìn)用戶(hù)模型

通過(guò)1.2對(duì)用戶(hù)模型的實(shí)現(xiàn)和1.3用戶(hù)模型的缺陷中可知,用戶(hù)模型雖然易于理解,抽象層次高,但對(duì)系統(tǒng)性能的開(kāi)銷(xiāo)非常大,并且1.2中的業(yè)務(wù)邏輯方法既要獲取數(shù)據(jù)又要執(zhí)行數(shù)據(jù)庫(kù)操作,不符合高內(nèi)聚低耦合的程序設(shè)計(jì)原則。為解決用戶(hù)模型對(duì)系統(tǒng)資源的依賴(lài),且使得代碼充分解耦,利用生產(chǎn)者消費(fèi)者對(duì)用戶(hù)模型進(jìn)行改進(jìn):

首先將業(yè)務(wù)邏輯的處理分為數(shù)據(jù)準(zhǔn)備、數(shù)據(jù)存儲(chǔ)、數(shù)據(jù)持久化三個(gè)過(guò)程;

生產(chǎn)者負(fù)責(zé)數(shù)據(jù)準(zhǔn)備過(guò)程,主要完成獲取數(shù)據(jù),數(shù)據(jù)封裝操作;數(shù)據(jù)倉(cāng)庫(kù)負(fù)責(zé)臨時(shí)存儲(chǔ)數(shù)據(jù);消費(fèi)者負(fù)責(zé)數(shù)據(jù)持久化過(guò)程;

生產(chǎn)者和消費(fèi)者以多線(xiàn)程的方式對(duì)數(shù)據(jù)進(jìn)行并發(fā)處理。

對(duì)用戶(hù)模型的改進(jìn),這里主要使用兩種方式來(lái)實(shí)現(xiàn):一種是單生產(chǎn)者-單消費(fèi)者方式,一種是多生產(chǎn)者-多消費(fèi)者方式。其中單生產(chǎn)者-單消費(fèi)者方式在數(shù)據(jù)準(zhǔn)備過(guò)程中,對(duì)于所有的數(shù)據(jù)都通過(guò)一個(gè)生產(chǎn)者來(lái)負(fù)責(zé),雖然通過(guò)數(shù)據(jù)倉(cāng)庫(kù)可以保證系統(tǒng)中產(chǎn)生的Student對(duì)象不會(huì)占用過(guò)多的內(nèi)存空間,但這樣的執(zhí)行效率顯然不高。所以使用多生產(chǎn)者方式來(lái)實(shí)現(xiàn),即多個(gè)生產(chǎn)者并行生產(chǎn)數(shù)據(jù),比如10w條數(shù)據(jù),若使用10個(gè)生產(chǎn)者,那么每個(gè)生產(chǎn)者平均負(fù)責(zé)生產(chǎn)1W條數(shù)據(jù),忽略線(xiàn)程等待的時(shí)間,10w條數(shù)據(jù)生產(chǎn)完的時(shí)間相當(dāng)于10個(gè)生產(chǎn)者都生產(chǎn)完1w條數(shù)據(jù)的時(shí)間。也就是說(shuō),將原來(lái)一個(gè)生產(chǎn)者生產(chǎn)10w條數(shù)據(jù)的任務(wù)交個(gè)10個(gè)生產(chǎn)者去完成,這樣的執(zhí)行效率會(huì)有顯著提升。如圖5改進(jìn)后的用戶(hù)模型業(yè)務(wù)處理流程。

實(shí)現(xiàn)代碼如下:

數(shù)據(jù)倉(cāng)庫(kù):

public class DataWarehouse {

private static int ?MAX_SIZE=5;//倉(cāng)庫(kù)大小

public static boolean isFinish=false;//生產(chǎn)過(guò)程是否結(jié)束

private BlockingQueue> dw=new LinkedBlockingQueue<>();//緩沖區(qū)

//生產(chǎn)者生產(chǎn)數(shù)據(jù)

public synchronized void addDatas(List datas){

while(dw.size()>=MAX_SIZE){

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

dw.add(datas);

this.notifyAll();//喚醒所有等待的線(xiàn)程,主要喚醒消費(fèi)者,防止死鎖

}

//消費(fèi)者消費(fèi)數(shù)據(jù)

public synchronized List consumeDatas(){

while(dw.size()<=0){

if(isFinish){//表示生產(chǎn)過(guò)程結(jié)束,且緩沖區(qū)為空,此時(shí)結(jié)束消費(fèi)過(guò)程

this.notifyAll();

return null;

}

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

List list=dw.poll();

this.notifyAll();//喚醒所有在等待的線(xiàn)程,主要喚醒生產(chǎn)者

return list;

}

public BlockingQueue> getData(){

return dw;

}

}

生產(chǎn)者(單生產(chǎn)者方式):

public class Producter extends ?Thread{

private DataWarehouse dataWarehouse;//數(shù)據(jù)倉(cāng)庫(kù)

private InputStream inputStream;//輸入流

private String fileName;//文件名

private TransDataUtil transDataUtil;//數(shù)據(jù)封裝類(lèi),將excel數(shù)據(jù)封裝成業(yè)務(wù)對(duì)象

public void run() {

//遍歷數(shù)據(jù)源,獲取數(shù)據(jù)單元,數(shù)據(jù)單元的大小不宜過(guò)大也不宜過(guò)小,過(guò)大會(huì)占用內(nèi)存空間,過(guò)小會(huì)增加與數(shù)據(jù)庫(kù)交互的次數(shù)和頻率,根據(jù)實(shí)驗(yàn)和研究,這里將單元大小設(shè)置成1000

if(list.size()>=1000){

dataWarehouse.addDatas(new ArrayList<>(list));//通過(guò)數(shù)據(jù)倉(cāng)庫(kù)生產(chǎn)數(shù)據(jù)

list.clear();

}

DataWarehouse.isFinish=true;//表示生產(chǎn)數(shù)據(jù)結(jié)束

}

}

生產(chǎn)者(多生產(chǎn)者方式):

public class Producter extends ?Thread{

private DataWarehouse dataWarehouse;

private Sheet sheet;

private int start;//開(kāi)始行

private int size;//數(shù)據(jù)源大小

private TransDataUtil transDataUtil;

public void run() {

Row row=null;

Cell cell=null;

List list=new ArrayList<>();

for (int i=this.start;i

row=sheet.getRow(i);

Integer columns= (int)row.getLastCellNum();

List rowData=new ArrayList<>();

for (int m=0;m

cell=row.getCell(m);

if (cell!=null) {

rowData.add(ExcelUtil. getCellValue(cell));

}else{

rowData.add("");

}

}

//將rowData轉(zhuǎn)化成對(duì)象Student放到list中

Student t=transDataUtil.transData(rowData);

list.add(t);

if(list.size()>=1000){//設(shè)置一個(gè)數(shù)據(jù)單元大小為1000

dataWarehouse.addDatas(new ArrayList<>(list));

list.clear();

}

}

if (list.size()>0) {

dataWarehouse.addDatas(list);

}

list=null;

DataWarehouse.isFinish=true;

}

}

消費(fèi)者:

public class Consumer extends ?Thread{

private DataWarehouse dataWarehouse;

private StudentService studentService;//業(yè)務(wù)邏輯類(lèi),負(fù)責(zé)業(yè)務(wù)邏輯的處理

public void run() {

while(true){

List studentList=dataWare-house.consumeDatas();//通過(guò)數(shù)據(jù)倉(cāng)庫(kù)取出數(shù)據(jù)

if (studentList==null) {

break;

}else if (studentList.size()>0) {

studentService.addStudentBatch(studentList);

studentList=null;

System.gc();

}

}

}

}

業(yè)務(wù)邏輯方法:(單生產(chǎn)者-單消費(fèi)者):

public boolean uploadExcelByPC(InputStream in, MultipartFile file){

DataWarehouse.isFinish=false;

producter.setFileName(file.getOriginalFilename());

producter.setInputStream(in);

new Thread(producter,"producter").start();

new Thread(consumer,"consumer").start();

return true;

}

業(yè)務(wù)邏輯方法:(多生產(chǎn)者-多消費(fèi)者):

public boolean uploadExcelByPC(InputStream in, MultipartFile file){

DataWarehouse.isFinish=false;

List threadList=new ArrayList<>();

try {

Workbook wb = ExcelUtil.getWorkBook(in, file.getOriginalFilename());

if (wb!=null) {

Sheet sheet = null;

Row row = null;

Cell cell = null;

for (int i=0;i

sheet=wb.getSheetAt(i);

if (sheet==null){ continue;}

producter.setSheet(sheet);

int size=sheet.getLastRowNum();

int pSize=5000;//表示一個(gè)生產(chǎn)者負(fù)責(zé)生產(chǎn)5000條數(shù)據(jù)

int start=0;

int index=0;

while(size>=pSize && size>0){

producter.setSize(pSize);

producter.setStart(start);

start+=pSize;

size-=pSize;

threadList.add(new Thread(producter,"producter-"+index));

index++;

}

if (size>0){

producter2.setSize(size);

producter2.setStart(start);

threadList.add(new Thread(producter,"producter-"+index));

}

}

}

for (Thread t:threadList) {t.start();}

new Thread(consumer,"consumer1").start();

new Thread(consumer,"consumer2").start();

} catch (Exception e) {

e.printStackTrace();

}

return true;

}

3.2 ?性能分析

執(zhí)行3.1中的實(shí)現(xiàn)代碼,并監(jiān)控jvm的內(nèi)存使用情況,如下圖為改進(jìn)后的用戶(hù)模型處理不同數(shù)據(jù)量時(shí)系統(tǒng)內(nèi)存的使用情況。

從圖7中可以看出,系統(tǒng)將文件流緩沖到WorkBook對(duì)象中后,系統(tǒng)占用內(nèi)存從150M左右增加到700M以上,之后便維持在700M左右呈峰式不斷變化,這是因?yàn)閿?shù)據(jù)倉(cāng)庫(kù)的作用,對(duì)系統(tǒng)中封裝的Student對(duì)象的內(nèi)存占用情況進(jìn)行了良好的控制,又因?yàn)槎嗌a(chǎn)者與多消費(fèi)者的并發(fā)操作,系統(tǒng)中不斷產(chǎn)生的Student對(duì)象使用后被及時(shí)回收,系統(tǒng)吞吐量也有了顯著提升。相比于圖3中呈緩慢上升式的曲線(xiàn)而言,改進(jìn)后的用戶(hù)模型更能適用于一定數(shù)據(jù)量的處理任務(wù)。

如表1不同數(shù)據(jù)規(guī)模下用戶(hù)模式改進(jìn)前后的性能對(duì)比。

從上表中可以看出,生產(chǎn)者消費(fèi)者模式對(duì)用戶(hù)模型性能的影響,改進(jìn)后的用戶(hù)模型不僅保持了原來(lái)的高度抽象、易于理解和實(shí)現(xiàn)的優(yōu)點(diǎn),還解決了內(nèi)存溢出的問(wèn)題,在一定程度上對(duì)用戶(hù)模型進(jìn)行了優(yōu)化,擴(kuò)展了用戶(hù)模型的應(yīng)用場(chǎng)景。

但是使用用戶(hù)模型,系統(tǒng)的時(shí)間消耗受到極大影響,就比如表1中處理10萬(wàn)條數(shù)據(jù)要花費(fèi)327432ms,這樣的執(zhí)行效率是不可觀的。影響時(shí)間的因素涉及到多方面,比如:多線(xiàn)程對(duì)資源的競(jìng)爭(zhēng)、數(shù)據(jù)庫(kù)的多表處理、SQL優(yōu)化問(wèn)題、程序代碼的時(shí)間復(fù)雜度、I/O流的優(yōu)化[5]等,由于文章篇幅有限且時(shí)間消耗問(wèn)題不是本文討論的重點(diǎn),所以不再詳細(xì)分析。

4 ?結(jié)論

經(jīng)過(guò)對(duì)用戶(hù)模型在實(shí)際應(yīng)用中的弊端以及產(chǎn)生原因的充分分析,展示了在不同數(shù)據(jù)規(guī)模下的系統(tǒng)性能消耗,利用生產(chǎn)者消費(fèi)者模式的思想,對(duì)用戶(hù)模式進(jìn)行重構(gòu),使得用戶(hù)模型中各個(gè)角色的職能分離、交互協(xié)作,并通過(guò)多線(xiàn)程并發(fā)編程的實(shí)現(xiàn)方式,解決了在一定數(shù)據(jù)量條件下的excel數(shù)據(jù)讀取問(wèn)題,節(jié)省了系統(tǒng)的部分內(nèi)存消耗,提升了業(yè)務(wù)處理效率。讓用戶(hù)模型在原有的高度抽象、易于理解等特性的基礎(chǔ)上,減輕了對(duì)系統(tǒng)資源的依賴(lài),擴(kuò)展了用戶(hù)模型的應(yīng)用場(chǎng)景。雖然還不能完全解決用戶(hù)模型對(duì) ?系統(tǒng)資源的依賴(lài),但對(duì)用戶(hù)模型的內(nèi)存占用做出了一定程度的優(yōu)化,關(guān)于用戶(hù)模型的缺陷仍然在不斷研究。

參考文獻(xiàn)

[1] Apache POI docs[EB/OL]. [2019-4-16]. http://poi.apache. org/components/spreadsheet/index. html.

[2] 李騰. 批量數(shù)據(jù)優(yōu)化處理框架的設(shè)計(jì)和實(shí)現(xiàn)[D]. 山東大學(xué), 2015.

[3] 路勇. Java多線(xiàn)程同步問(wèn)題分析[J]. 軟件, 2012, 33(4): 31-33

[4] 吉豪杰. 大數(shù)據(jù)時(shí)代下基于SSM框架的高校畢業(yè)生檔案管理系統(tǒng)的研發(fā)設(shè)計(jì)[J]. 軟件, 2018, 39(11): 151-158.

[5] 馬凱航, 高永明, 吳止鍰等. 大數(shù)據(jù)時(shí)代數(shù)據(jù)管理技術(shù)研究綜述[J]. 軟件, 2015, 36(10): 46-49

[6] 左大鵬, 徐薇. 基于Hadoop 處理小文件的優(yōu)化策略[J]. 軟件, 2015, 36(2): 107-111

[7] 朝格. 淺談EXCEL與XML的數(shù)據(jù)交換[J]. 軟件, 2012, 33(5): 48-50

[8] 張強(qiáng). 創(chuàng)建型模式在題型庫(kù)設(shè)計(jì)中的應(yīng)用[J]. 軟件, 2012, 33(3): 69-71

[9] 胡泳霞. 基于內(nèi)存模型的Java并發(fā)編程[J]. 電子測(cè)試, 2016(13): 89-90.

[10] 張志強(qiáng), 王偉鈞, 施達(dá). 一種大容量數(shù)據(jù)文件抽取算法的優(yōu)化研究[J]. 成都大學(xué)學(xué)報(bào)(自然科學(xué)版), 2019(01): 52-55.

[11] 勞加慶, 葉飛躍, 張國(guó)平. 多線(xiàn)程技術(shù)對(duì)批量數(shù)據(jù)處理的優(yōu)化[J]. 微型機(jī)與應(yīng)用, 2001(04): 11-12.

猜你喜歡
設(shè)計(jì)模式
設(shè)計(jì)模式識(shí)別的特征信息分類(lèi)研究
“1+1”作業(yè)設(shè)計(jì)模式的實(shí)踐探索
基于能力目標(biāo)培養(yǎng)的藥學(xué)專(zhuān)業(yè)課程整體教學(xué)設(shè)計(jì)模式研究
引入線(xiàn)索約束的設(shè)計(jì)模式變體挖掘研究*
設(shè)計(jì)模式挖掘的有效性評(píng)估策略
智慧圖書(shū)館環(huán)境下的融貫式服務(wù)設(shè)計(jì)模式研究
三維協(xié)同設(shè)計(jì)模式下的航天項(xiàng)目管理實(shí)踐與展望
交通機(jī)電工程設(shè)計(jì)模式創(chuàng)新探討
應(yīng)用型高校學(xué)生程序設(shè)計(jì)能力培養(yǎng)研究
基于“雙師制”指導(dǎo)下的工業(yè)設(shè)計(jì)專(zhuān)業(yè)畢業(yè)設(shè)計(jì)模式
康定县| 广汉市| 贡嘎县| 邻水| 沂南县| 五寨县| 潼关县| 上虞市| 洛川县| 江门市| 宣化县| 临武县| 谢通门县| 天台县| 平武县| 荥经县| 瑞丽市| 满城县| 三门县| 武夷山市| 共和县| 喀喇| 房山区| 广平县| 大名县| 黄平县| 金堂县| 珠海市| 崇义县| 舒兰市| 扎囊县| 定远县| 浪卡子县| 阳东县| 英超| 韶山市| 锡林浩特市| 莫力| 容城县| 黄大仙区| 无锡市|