鍍金池/ 問答/Java  Linux  數(shù)據(jù)庫/ tomcat 頻繁觸發(fā)full gc

tomcat 頻繁觸發(fā)full gc

服務(wù)器:tomcat
簡單描述:db中有460w+條記錄,在@Service中,使用while true,一次從DAO層中select 出500條,逐條處理,處理完之后再select 出500條,直到select出來是空的list,就break;
問題:由于總共有460w條數(shù)據(jù),還是逐條處理,所以程序跑了24小時都沒有跑完,有沒有可能出現(xiàn)full gc?如果出現(xiàn)full gc,原因可能是什么?
示意代碼:

public void doProcess(){
        while (true){
            List<UserDTO> list = myDao.selectUserPage();
            if (list.size()>0){
                for (UserDTO userDTO:list){
                    //處理業(yè)務(wù)邏輯,每500條大致需要30多秒
                }
            }else {
                break;
            }
        }
    }
回答
編輯回答
茍活

1 有可能頻繁產(chǎn)生full gc,并且由于對象過多無法釋放導(dǎo)致oom。 比如下面代碼塊,通過map又增加了userDTO的引用。

 Map map = ...
 for (userDTO userDTO:list){
    map.put(userDTO.getname(), userDTO);              
 }

2 這種數(shù)據(jù)量大的計算,可以考慮用存儲過程來實現(xiàn),計算效率會大幅提高。

2017年1月23日 04:16
編輯回答
萢萢糖

一般來說的數(shù)據(jù)庫每秒可以讀取一萬到幾萬的記錄,如果你是從執(zhí)行一條一次sql語句的結(jié)果中取460w記錄,應(yīng)該10分鐘之內(nèi),就可以讀完。所以問題應(yīng)該是要么myDao.selectUserPage()花了太長時間,要么就像你注釋上說的處理業(yè)務(wù)邏輯,每500條大致需要30多秒。如果是處理業(yè)務(wù)邏輯太慢,可以用多線程加快速速。我推薦一個框架: Abacus-Util,你可以試一下:

static final SQLExecutor sqlExecutor = new SQLExecutor(JdbcUtil.createDataSource(driver, url, user, password));

// sql 是一次性取出所有結(jié)果的SQL,不帶分頁的。
// 雖然SQL是一次取出所有結(jié)果,但由于下面的Stream lazy load,所以結(jié)果只是一條一條讀到內(nèi)存里,處理一條就會扔掉,不會把所有的460W記錄同時保存在內(nèi)存。
// parameters 是 sql 參數(shù),可以不寫,如果SQL沒有參數(shù)。
sqlExecutor.stream(UserDTO.class, sql, parameters).run(s -> s.parallel(threadNum).forEach(userDTO -> {
    // 處理業(yè)務(wù)邏輯
}));
2018年6月30日 09:49
編輯回答
萌二代

不會
list重新賦值的時候,之前的值就成了垃圾,會被回收。

2017年11月4日 00:15
編輯回答
維她命

具體還要看你業(yè)務(wù)邏輯里有沒有持有userDTO的引用沒有釋放,若沒有的話應(yīng)該就不是gc的問題。
建議用jstatck來dump線程快照看看

2018年5月6日 11:25
編輯回答
笨尐豬

如果不看你業(yè)務(wù)邏輯部分代碼,單看你這段邏輯,理論上不會Full GC的(你的內(nèi)存不至于連500條記錄都存儲不下的吧),當(dāng)然,你的程序必須是單線程的,如果是多線程(而且線程數(shù)還比較高)則有可能。出于程序健壯性考慮,你的判斷語句list.size() > 0最好能改成list != null && list.size() > 0。

2017年2月16日 09:14
編輯回答
孤毒

少年,我來給你做一道數(shù)學(xué)題,460w / 500 * 0.5分鐘 / 60 = 76.67 小時,所以24小時沒處理完是正常的。

2018年2月9日 09:51
編輯回答
逗婦乳

很低的可能性導(dǎo)致full gc的,以你的邏輯,每次500條的產(chǎn)生對象幾乎引用范圍在新生代就被回收掉了。

2018年7月25日 17:43
編輯回答
別逞強

最重要的是,數(shù)據(jù)庫是本地還是跨網(wǎng)

2017年3月16日 02:30
編輯回答
雨萌萌

還存在一個問題,如果處理能力能達到的話,查出來list若為空,list.size()這句是會報空指針異常的,所以為空判斷應(yīng)該放前面,為空則break。

2017年12月7日 02:16