關於Java中單執行緒處理資料過慢的問題解決
阿新 • • 發佈:2018-12-26
有個需求呼叫了外部介面查詢客戶的違章資訊,一共一千多輛車,檢視日誌的時候這段程式居然跑了有半個多小時。
之前的處理邏輯是將所有的資料遍歷,根據客戶的車輛資訊一個個去呼叫介面。
這麼長時間,肯定要優化。想了想:可以將查出來的所有資料分片,分n片,啟動n個執行緒,分別去執行查介面的功能。由於公司使用的伺服器一般四核cpu,所以使用可以將資料分成8片,並啟動8個執行緒。(一個併發程式開多少執行緒合適?)
一、首先是啟動8個執行緒,這裡使用了JUC的執行緒池。
有一篇專門介紹建立執行緒池的方法:《Java ExecutorService四種執行緒池的例子與說明》
二、然後將資料分片
之前也專門寫過一個文章,可以出門左拐,這裡就不詳細介紹了。 ==》List分片處理
三、處理資料
由於是單機程式,是將所有的資料查出來,然後分片處理,所以不會出現各種併發型別問題。但是還是有一個小小的問題,之前計算這段程式的處理時間失效了。原因是之前用主執行緒記錄時間,程式也跑在主執行緒上,所以只需要在程式的前後new 兩個時間,計算差值就可以了。現在使用子執行緒處理資料後,這樣處理就不可以了。
之前處理執行時間的邏輯:
@RequestMapping("send-break-rules-msg") public void sendMsgToClient() { Date startDate = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); log.info("<<<<<<<<<<<<<<<send break rules msg start at:{}>>>>>>>>>>>>>>", sdf.format(startDate)); // 從資料庫查資料 // ...... // 查詢外部介面,處理資料 Date endDate = new Date(); log.info("<<<<<<<<<<<<<<<send break rules msg end at:{}>>>>>>>>>>>>>>", sdf.format(endDate)); log.info("<<<<<<<<<<<<<<<send break rules msg cost:{}>>>>>>>>>>>>>>", endDate.getTime() - startDate.getTime()); }
在主執行緒中使用CountDownLatch工具類,在每個子執行緒的處理邏輯最後加上 countDownLatch.countDown();
經過這樣的處理之後,這段程式完美的別控制在了5分鐘以內。