尹隆波
摘要:大型數(shù)據(jù)運(yùn)用場景中存在數(shù)據(jù)進(jìn)行關(guān)聯(lián)或更新操作的需求,在實(shí)際應(yīng)用中通過單獨(dú)部署定時(shí)任務(wù)系統(tǒng)周期性去統(tǒng)計(jì)或更新數(shù)據(jù)。由于龐大而復(fù)雜的數(shù)據(jù),定時(shí)任務(wù)系統(tǒng)中的任務(wù)運(yùn)行起來耗時(shí)很長而且會過多地消耗系統(tǒng)的資源,對系統(tǒng)的性能造成很大的影響。另外,復(fù)雜的定時(shí)任務(wù)系統(tǒng)中出現(xiàn)問題很難去排查并進(jìn)行分析?;谝陨蠁栴},論文通過合理的利用多線程技術(shù)、采用增量更新數(shù)據(jù)、合理設(shè)置不同子定時(shí)任務(wù)的運(yùn)行時(shí)間和周期來提高系統(tǒng)處理速度,并且采用擴(kuò)展ThreadPoolExecutor統(tǒng)計(jì)線程運(yùn)行情況、給每個(gè)線程設(shè)置有意義的名稱以方便系統(tǒng)中的問題排查分析。
關(guān)鍵詞: 高并發(fā);定時(shí)任務(wù);線程池;負(fù)載均衡;JAVA
中圖分類號:TP311 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2018)33-0025-03
大型數(shù)據(jù)運(yùn)用場景中,通常需要展示一個(gè)對象關(guān)聯(lián)的其他類型對象的數(shù)量,并且其關(guān)聯(lián)的其他類型數(shù)據(jù)出于不斷地動態(tài)地增加中。通常巨量的對象數(shù)據(jù)存儲在如Solr、ElaticSearch等非關(guān)系型數(shù)據(jù)庫中。非關(guān)系型數(shù)據(jù)中,多個(gè)表之間沒有提供直接的關(guān)聯(lián)操作。運(yùn)行單獨(dú)的定時(shí)統(tǒng)計(jì)任務(wù)來計(jì)算對象關(guān)聯(lián)的其他類型對象數(shù)量以及動態(tài)增加新關(guān)聯(lián)的對象,是處理上述問題的一種實(shí)用解決方案。一方面,定時(shí)任務(wù)能夠及時(shí)統(tǒng)計(jì)或更新關(guān)聯(lián)數(shù)據(jù)滿足客戶的展示需要;另一方面,利用定時(shí)任務(wù)進(jìn)行統(tǒng)計(jì),能夠大幅度減少頁面過程中后臺程序復(fù)雜計(jì)算的時(shí)間,使得頁面加載的時(shí)長控制在用戶接受范圍內(nèi)。
基于Java 開發(fā)的Web系統(tǒng),可以采用JDK提供的Shedular框架運(yùn)行定時(shí)任務(wù),使用簡單并且高效。為了提高定時(shí)任務(wù)的運(yùn)行效率、以及方便問題定位分析,論文將根據(jù)實(shí)際應(yīng)用中的解決辦法從這兩個(gè)目標(biāo)進(jìn)行闡述。
1 提高系統(tǒng)處理速度
大型數(shù)據(jù)運(yùn)用場景中,通常定時(shí)任務(wù)系統(tǒng)需要處理的數(shù)據(jù)量巨大,為了提高定時(shí)任務(wù)系統(tǒng)的處理速度,可以從以下三方面考慮。一是利用多線程技術(shù)進(jìn)行并發(fā)處理;二是采用增量更新數(shù)據(jù)的策略;三是合理地設(shè)置定時(shí)任務(wù)數(shù)量,以及合理安排多個(gè)子定時(shí)任務(wù)的運(yùn)行時(shí)間和運(yùn)行周期。
1.1 多線程并發(fā)處理
為了提高系統(tǒng)數(shù)據(jù)處理的速度,在多CPU的服務(wù)器上,可以采用多線程技術(shù)充分利用多個(gè)CPU的計(jì)算能力。通常開發(fā)者可以將一個(gè)定時(shí)任務(wù),拆分成可以獨(dú)立運(yùn)行的若干個(gè)細(xì)小子任務(wù),然后為每一個(gè)子任務(wù)單獨(dú)創(chuàng)建個(gè)線程運(yùn)行。如果拆分的子定時(shí)任務(wù)數(shù)量過多,系統(tǒng)中運(yùn)行的線程數(shù)量也會過多,由于每個(gè)線程的創(chuàng)建需要一定的系統(tǒng)資源和時(shí)間開銷,大量的線程會降低系統(tǒng)的響應(yīng)速度和性能。因此,需要合理地設(shè)置系統(tǒng)中運(yùn)行的線程數(shù)量。簡單來說,Java并發(fā)有兩種類型:計(jì)算密集型并發(fā)和IO密集型并發(fā)。
1) 計(jì)算密集型并發(fā)
計(jì)算密集型,從名稱的定義上來看,就是一個(gè)應(yīng)用需要數(shù)量龐大的CPU資源進(jìn)行數(shù)據(jù)計(jì)算操作。進(jìn)入21世紀(jì)后,信息技術(shù)步入了多核CPU服務(wù)器時(shí)代,讓每一個(gè)CPU核心都參與數(shù)據(jù)計(jì)算,將多核CPU的性能充分利用起來,這樣才能最高效率地使用服務(wù)器硬件資源。在裝載成百上千CPU的服務(wù)器配置上運(yùn)行單線程任務(wù),是對寶貴的硬件資源的最大浪費(fèi)。對于計(jì)算密集型的應(yīng)用,主要是靠CPU的運(yùn)算能力來工作,消耗CPU資源,大部分時(shí)間用來運(yùn)行計(jì)算、邏輯判斷等CPU動作,比如計(jì)算圓周率、對視頻進(jìn)行高清解碼等,通常這些應(yīng)用訪問I/O設(shè)備頻率較低。為了發(fā)揮CPU密集并發(fā)應(yīng)用的性能優(yōu)勢,需要盡量避免過多的線程頻繁地進(jìn)行上下文切換,一種比較比合理的方案是:線程數(shù)量 = CPU核數(shù) + 1。
另外一種較為理想的方法是:線程數(shù)量 = CPU核數(shù) * 2。除了考慮CPU的內(nèi)核數(shù)量,另外還要參考JDK的使用版本,以及CPU的硬件配置(現(xiàn)在部分服務(wù)器的CPU支持超線程機(jī)制)。JDK 1.8后,JAVA默認(rèn)支持并行計(jì)算,因此,基于JDK1.8或更高的JAVA版本,計(jì)算密集型應(yīng)用的合理方案是:線程數(shù) = CPU核數(shù) * 2??梢酝ㄟ^JDK提供的接口從運(yùn)行的JVM環(huán)境中獲取服務(wù)器的CPU數(shù)量。
2) IO密集型并發(fā)
顧名思義,IO密集型的應(yīng)用,大部分的時(shí)間在等待IO讀寫操作上,而CPU占用率并不高。目前大部分軟件項(xiàng)目都是Web應(yīng)用,一方面涉及大量而頻繁的網(wǎng)絡(luò)信息傳輸,另一方面,程序應(yīng)用與數(shù)據(jù)庫系統(tǒng)、與緩存間的數(shù)據(jù)交互也需要大量的IO讀寫。一旦發(fā)生IO讀寫操作,線程會一直等待IO操作的運(yùn)行,直到IO操作完成、數(shù)據(jù)準(zhǔn)備好后,線程才會繼續(xù)執(zhí)行后續(xù)步驟。通常IO讀寫操作時(shí)間較長(主要受到磁盤讀寫速度和網(wǎng)絡(luò)傳輸帶寬的限制),這時(shí)線程處于等待狀態(tài),而CPU處于空閑狀態(tài), 此時(shí)可以運(yùn)行其他非等待狀態(tài)的線程,處理其他的工作,從而提高系統(tǒng)的并發(fā)量。因此對于IO密集型的應(yīng)用,應(yīng)該將同時(shí)運(yùn)行的線程數(shù)量設(shè)置大些。
但同時(shí)運(yùn)行的線程數(shù)量也不能設(shè)置過大,線程數(shù)量應(yīng)當(dāng)每個(gè)子任務(wù)處于阻塞狀態(tài)的時(shí)間比例相關(guān)。假設(shè)每個(gè)子任務(wù)平均的50%時(shí)間處于阻塞狀態(tài),那么定時(shí)任務(wù)系統(tǒng)同時(shí)運(yùn)行的線程數(shù)量應(yīng)當(dāng)是服務(wù)器CPU核數(shù)的兩倍。換而言之,應(yīng)用中的線程數(shù)量應(yīng)當(dāng)同CPU的數(shù)量成正比,而和每個(gè)子任務(wù)IO的平均阻塞時(shí)間占比率成反比?;贑PU和阻塞時(shí)間占比,開發(fā)人員可以計(jì)算出程序所需的線程數(shù)。對于IO密集型應(yīng)用,目前歸納出了一套公式:線程數(shù)量=CPU核數(shù)/(1-阻塞系數(shù))。
公式中的阻塞系數(shù)一般在0.8和0.9之間取值,也可以是0.8或者0.9?;谏鲜龉?,對于一個(gè)密集型應(yīng)用系統(tǒng),假設(shè)服務(wù)器CPU數(shù)量為16,則其較為合適的線程數(shù)量應(yīng)當(dāng)是80到160之間,但這也不是絕對的,可以根據(jù)系統(tǒng)的實(shí)際情況以及運(yùn)行狀況來合理調(diào)整。
1.2 增量更新數(shù)據(jù)
在一些大數(shù)據(jù)運(yùn)用場景中,上游應(yīng)用中的信息數(shù)據(jù)每時(shí)每刻都在發(fā)生變化,而依賴這些數(shù)據(jù)的下游系統(tǒng)需要運(yùn)行定時(shí)任務(wù)系統(tǒng)來周期性刷新這些變化的數(shù)據(jù)。當(dāng)數(shù)據(jù)量小時(shí)候,可以采用簡單粗暴的方式—每次任務(wù)進(jìn)行全量的數(shù)據(jù)更新。但隨著系統(tǒng)業(yè)務(wù)的快速增長,應(yīng)用中的數(shù)據(jù)量成幾何方式增長時(shí),定時(shí)任務(wù)系統(tǒng)中的工作將極為耗時(shí)并且占用大量IO硬件資源。這種方式下,每個(gè)周期都需要從數(shù)據(jù)庫服務(wù)器上通過IO讀寫或同上游進(jìn)行數(shù)據(jù)的網(wǎng)絡(luò)傳輸,獲得全量的數(shù)據(jù)。當(dāng)傳輸?shù)臄?shù)據(jù)量過大時(shí),IO操作耗費(fèi)的時(shí)間會占比很大,并大量占用系統(tǒng)的IO資源,而IO能力通常是系統(tǒng)的瓶頸所在。
此時(shí),可以通過采購更多以及性能更好的硬件資源來處理不斷快速增長的數(shù)據(jù)。通常,這是這是一種不太可取的奢侈方案。不過可以轉(zhuǎn)換一種思路,將全量更新機(jī)制替換為增量更新。雖然數(shù)據(jù)量總量十分龐大,但一段時(shí)間內(nèi)發(fā)生變化的數(shù)據(jù)量一般是有限的,定時(shí)任務(wù)系統(tǒng)在每個(gè)周期內(nèi)只需增量處理周期內(nèi)更新的數(shù)據(jù)即可,這樣可以很大程度上降低定時(shí)任務(wù)系統(tǒng)的IO時(shí)間開銷,并節(jié)省寶貴的IO資源。
增量更新的基礎(chǔ)是全量數(shù)據(jù),最初可以采用某種方式先把全量數(shù)據(jù)拷貝存入業(yè)務(wù)系統(tǒng)。然后運(yùn)行定時(shí)任務(wù)去周期性更新一段時(shí)間內(nèi)增加或變化的數(shù)據(jù)。增量更新,一般是讀取某個(gè)時(shí)刻(更新時(shí)間)或者檢查點(diǎn)(checkpoint)之后的信息數(shù)據(jù)來處理,而不是粗暴的讀取全量數(shù)據(jù)。雖然增量更新會造成一定的額外空間開銷,需要對每條數(shù)據(jù)記錄采用時(shí)間或checkpoint標(biāo)識和記錄更新點(diǎn),但從整體上考慮,這是十分必要的。
1.3 合理設(shè)置定時(shí)任務(wù)數(shù)量,合理安排運(yùn)行時(shí)間
大型數(shù)據(jù)運(yùn)用場景中,需要進(jìn)行統(tǒng)計(jì)或增量更新的對象類型繁多,定時(shí)任務(wù)處理的事情龐大而復(fù)雜。這種場景下,應(yīng)當(dāng)避免將所有的功能邏輯放在一個(gè)大而全的定時(shí)任務(wù)中,而是合理地拆分一個(gè)大而全的定時(shí)任務(wù),將定時(shí)任務(wù)細(xì)分成若干個(gè)獨(dú)立、互不影響的小的定時(shí)任務(wù),每個(gè)定時(shí)任務(wù)處理同一種或幾種相互關(guān)聯(lián)類型的數(shù)據(jù)。一方面可以提高系統(tǒng)并行的處理速度,另一方面,可以在不同的時(shí)間段內(nèi)運(yùn)行合適的定時(shí)任務(wù)從而實(shí)現(xiàn)時(shí)間概念上的負(fù)載均衡。
將大的任務(wù)細(xì)分后,一些任務(wù)執(zhí)行周期較短的,如兩三個(gè)小時(shí)左右的,可以考慮放在系統(tǒng)業(yè)務(wù)不繁忙的時(shí)候觸發(fā),如凌晨兩三點(diǎn),避免與正在運(yùn)行的關(guān)鍵業(yè)務(wù)系統(tǒng)競爭IO、CPU等資源。另外,盡量將不同定時(shí)任務(wù)的運(yùn)行時(shí)間錯(cuò)開,降低一段時(shí)間內(nèi)的系統(tǒng)負(fù)荷,尤其是業(yè)務(wù)繁忙的時(shí)間段。同時(shí),需要合理地考慮每個(gè)子定時(shí)任務(wù)運(yùn)行的周期。首先,任務(wù)周期需要超過通常情況下該任務(wù)運(yùn)行的最長時(shí)間;其次,定時(shí)任務(wù)的周期需要滿足大部分?jǐn)?shù)據(jù)及時(shí)性的要求。
2 方便問題定位分析
復(fù)雜而龐大的定時(shí)任務(wù)系統(tǒng)中,開發(fā)人員經(jīng)常要使用JDK提供的ThreadPoolExecutor框架類創(chuàng)建線程池來執(zhí)行大量的定時(shí)任務(wù),通過線程池的并發(fā)特性來提高定時(shí)任務(wù)系統(tǒng)的吞吐量。在程序開發(fā)過程中,合理地運(yùn)用線程池技術(shù)有以下三方面優(yōu)點(diǎn)。一是:降低系統(tǒng)資源的消耗。通過循環(huán)利用已經(jīng)創(chuàng)建的線程減少重新構(gòu)造線程和銷毀線程造成的資源消耗。二:提高系統(tǒng)的響應(yīng)速度。新的任務(wù)提交后,新任務(wù)直接利用已存在的線程就可以立刻執(zhí)行。三:提高線程的可管理性。使用線程池技術(shù)可以對線程這一稀缺資源進(jìn)行統(tǒng)一分配、調(diào)優(yōu)和監(jiān)控。
JDK提供了線程池技術(shù),為線程創(chuàng)建、銷毀的開銷問題和系統(tǒng)資源不足問題提供了很好的解決方案, 能有效地提高系統(tǒng)的響應(yīng)速度和服務(wù)系統(tǒng)的整體性能。但默認(rèn)的線程池框架在線程運(yùn)行情況統(tǒng)計(jì)、線程名稱展示存在不盡人意的地方?;赥hread PoolExecutor類存在的這兩個(gè)不足,論文提出了相應(yīng)的解決辦法。
2.1 擴(kuò)展Thread Pool Executor統(tǒng)計(jì)運(yùn)行情況
線程池使用不當(dāng)也會使服務(wù)器資源枯竭,導(dǎo)致異常情況的發(fā)生,比如固定線程池的阻塞隊(duì)列任務(wù)數(shù)量過多、內(nèi)存溢出、系統(tǒng)假死等問題。如果在定時(shí)任務(wù)系統(tǒng)中大量地使用線程池,則很有必要對運(yùn)行的線程池進(jìn)行必要的監(jiān)控,以便系統(tǒng)出現(xiàn)問題時(shí),可以根據(jù)線程池的運(yùn)行狀況快速定位問題原因,并分析問題。因此,定時(shí)任務(wù)系統(tǒng)中需要一種簡單而有效的監(jiān)控方案來監(jiān)控線程池的使用情況,比如完成任務(wù)數(shù)量、線程池大小、每個(gè)線程的運(yùn)行時(shí)間線程池中運(yùn)行的線程數(shù)量等信息。
基于以上的功能要求,在定時(shí)任務(wù)系統(tǒng)中可以對ThreadPoolExecutor類進(jìn)行一定的擴(kuò)展,在線程池中實(shí)現(xiàn)簡單的監(jiān)控功能,并實(shí)時(shí)將線程池運(yùn)行狀況信息打印到日志中,方便技術(shù)人員進(jìn)行問題排查、系統(tǒng)調(diào)優(yōu)。具體的思路如下:通過StatThreadPoolExecutor類繼承ThreadPoolExecutor類來自定義線程池,重寫默認(rèn)線程池的shutdown、shutdownNow、beforeExecute和afterExecute方法來統(tǒng)計(jì)線程池的執(zhí)行情況,這幾個(gè)方法是ThreadPoolExecutor類預(yù)留給程序開發(fā)人員進(jìn)行擴(kuò)展的方法,具體如下:
shutdown方法:線程池延遲關(guān)閉時(shí)(這一方法需要等待線程池里的所有任務(wù)都執(zhí)行完畢),統(tǒng)計(jì)已執(zhí)行完畢的任務(wù)數(shù)量、正在運(yùn)行的任務(wù)數(shù)量、還未執(zhí)行的任務(wù)數(shù)量。shutdownNow方法:線程池立即關(guān)閉時(shí)(這一方法無需等待線程池里的所有任務(wù)都執(zhí)行完畢),統(tǒng)計(jì)已執(zhí)行完畢的任務(wù)數(shù)量、正在運(yùn)行的任務(wù)數(shù)量、還未執(zhí)行的任務(wù)數(shù)量。beforeExecute(Thread t, Runnable r)方法:添加在任務(wù)執(zhí)行之前,記錄任務(wù)運(yùn)行開始的時(shí)間,通過Map保存每個(gè)任務(wù)運(yùn)行的開始時(shí)間,以任務(wù)的hashCode為key值,開始時(shí)間為value值。afterExecute(Runnable r, Throwable t)方法:任務(wù)執(zhí)行之后,計(jì)算任務(wù)結(jié)束時(shí)間。統(tǒng)計(jì)任務(wù)耗時(shí)、初始線程數(shù)、核心線程數(shù)、正在執(zhí)行的任務(wù)數(shù)量、已完成任務(wù)數(shù)量、任務(wù)總數(shù)、隊(duì)列里緩存的任務(wù)數(shù)量、池中存在的最大線程數(shù)、最大允許的線程數(shù)、線程空閑時(shí)間、線程池是否已經(jīng)關(guān)閉、線程池是否已經(jīng)終止信息。
在StatThreadPoolExecutor類構(gòu)造方法中,需要繼承ThreadPoolExecutor的構(gòu)造方法,但可以另外增加一個(gè)參數(shù),用來傳入線程池名稱參數(shù),該參數(shù)主要是用來給線程池定義一個(gè)與業(yè)務(wù)相關(guān)并有具體意義的線程池名字,方便進(jìn)行系統(tǒng)的運(yùn)維工作人員排查線上問題。
并發(fā)系統(tǒng)會依賴beforeExecute和afterExecute這兩個(gè)方法統(tǒng)計(jì)的信息。有了這些線程池運(yùn)行狀態(tài)信息之后,開發(fā)人員可以根據(jù)業(yè)務(wù)情況和統(tǒng)計(jì)的線程池的信息合理地調(diào)整線程池大小,并根據(jù)每個(gè)任務(wù)耗時(shí)長短對任務(wù)進(jìn)行性能分析。同時(shí),可以發(fā)現(xiàn)執(zhí)行時(shí)間過長的線程,然后可以根據(jù)具體程序分析這些任務(wù)耗時(shí)較多的原因,對定時(shí)任務(wù)程序進(jìn)行優(yōu)化,從而提高相應(yīng)的子定時(shí)系統(tǒng)的執(zhí)行速度。在生產(chǎn)環(huán)境中,應(yīng)當(dāng)盡量避免使用shutdown和shutdownNow方法,因?yàn)檎{(diào)用這兩個(gè)關(guān)閉線程池的方法之后,線程池會被關(guān)閉,不再接收新的任務(wù)。定時(shí)任務(wù)中需要判斷線程池內(nèi)的線程是否已全部執(zhí)行完畢,在線程數(shù)量固定的情況下可以使用并發(fā)工具包中的CountDownLatch來進(jìn)行判斷,在線程數(shù)量不固定的情況下,CountDownLatch就不再適用。這種場景下,可以通過判斷線程池中的等待隊(duì)列、和運(yùn)行狀態(tài)為active的線程數(shù)量來確定線程池中所有線程是否已執(zhí)行完畢。
2.2 定制線程名稱
Web項(xiàng)目中使用ThreadPoolExecutor進(jìn)行多線程開發(fā),使用起來很方便,但當(dāng)運(yùn)維的工作人員查看堆棧信息或者調(diào)試性能的時(shí)候,看到的線程名稱默認(rèn)都是pool-1-thread-1\2\3\4之類。如果系統(tǒng)中用到了多個(gè)線程池,排查系統(tǒng)故障時(shí)就無法區(qū)分是哪個(gè)線程產(chǎn)生的問題。使用JAVA默認(rèn)的線程池技術(shù),線程的每一次運(yùn)行都是不同的執(zhí)行結(jié)果,如果在排查問題時(shí)要想?yún)^(qū)分每一個(gè)線程,應(yīng)當(dāng)給每一個(gè)運(yùn)行的線程任務(wù)定義有意義的名稱,另外線程的名字應(yīng)當(dāng)在線程啟動之前進(jìn)行定義。
在ThreadPoolExecutor中所有的線程都是以pool-開頭的,因?yàn)榫€程池工廠中對線程設(shè)置的名字是固定格式的。如果需要修改默認(rèn)的線程名稱,需要擴(kuò)展自行定義并線程工廠ThreadFactory,在定制的線程工廠中重新設(shè)置線程運(yùn)行時(shí)的名稱。還有一種方法,線程在被調(diào)用后才會執(zhí)行run方法,run方法的執(zhí)行表示這個(gè)任務(wù)真正被線程運(yùn)行了,這時(shí)線程的名稱也就確定了,所以可以在任務(wù)線程的run方法中第一句添加定義線程名稱的語句。
3 總結(jié)
大數(shù)據(jù)運(yùn)用場景的定時(shí)任務(wù)系統(tǒng)中,使用多線程并發(fā)技術(shù)能大幅度提高系統(tǒng)的處理速度。在使用多線程機(jī)制的過程中,需要判斷系統(tǒng)各個(gè)模塊是IO密集型還是CPU密集型,然后合理地設(shè)置同時(shí)運(yùn)行的線程數(shù)目。在巨量的信息數(shù)據(jù)系統(tǒng)中,粗暴地使用全量數(shù)據(jù)來更新對定時(shí)任務(wù)系統(tǒng)來說是個(gè)很難完成的任務(wù),可以通過增加時(shí)間戳的方式,在每個(gè)周期內(nèi)增量更新一段時(shí)間內(nèi)的關(guān)聯(lián)數(shù)據(jù)。復(fù)雜的定時(shí)任務(wù)系統(tǒng)中一般拆分成多個(gè)子定時(shí)任務(wù),應(yīng)該合理地錯(cuò)開不同定時(shí)任務(wù)的運(yùn)行時(shí)間以及運(yùn)行周期,從而有效地降低系統(tǒng)的負(fù)載。
合理地運(yùn)用線程池技術(shù)可以降低系統(tǒng)資源的消耗、提高系統(tǒng)的響應(yīng)速度和提高線程的可管理性。但默認(rèn)的線程池框架沒有提供線程運(yùn)行情況統(tǒng)計(jì)、線程名稱展示的功能。通過擴(kuò)展線程池ThreadPoolExecutor,開發(fā)人員可以獲取線程池的運(yùn)行調(diào)度內(nèi)部細(xì)節(jié),對并發(fā)運(yùn)行的定時(shí)任務(wù)系統(tǒng)進(jìn)行故障排查、問題分析很有幫助。此外,開發(fā)過程中應(yīng)當(dāng)給每一個(gè)運(yùn)行的線程任務(wù)定義有意義的名稱,以便在排查問題時(shí)很輕易地區(qū)分每一個(gè)線程。
參考文獻(xiàn):
[1] 任冬艷, 廖建新, 王純. 基于 JDK1. 5 的定時(shí)任務(wù)執(zhí)行方案的改進(jìn)[J]. 計(jì)算機(jī)系統(tǒng)應(yīng)用, 2008(2):115-118.
[2] 豐洪才, 鄧華來, 劉年波. 定時(shí)任務(wù)在智能數(shù)碼監(jiān)控系統(tǒng)中的應(yīng)用[J]. 武漢工業(yè)學(xué)院學(xué)報(bào), 2004, 23(3): 1-3.
[3] 王華, 馬亮, 顧明. 線程池技術(shù)研究與應(yīng)用[J].計(jì)算機(jī)應(yīng)用研究,2005,22(11):141-142.
[4] 吳健. 基于并發(fā)控制機(jī)制的 Web 系統(tǒng)的開發(fā)技術(shù)研究[D]. 云南大學(xué), 2015.
[5] 吳高陽. 基于 NIO 的 Java 高性能網(wǎng)絡(luò)技術(shù)的研究與應(yīng)用[D]. 西安: 西安電子科技大學(xué), 2014.
[6] 周博. WEB 服務(wù)器負(fù)載均衡系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[D]. 電子科技大學(xué), 2014.
[7] 楊開杰, 劉秋菊, 徐汀榮. 線程池的多線程并發(fā)控制技術(shù)研究[J]. 計(jì)算機(jī)應(yīng)用與軟件, 2010 (1): 168-170.
[8]唐穎峰, 陳世平. 一種面向分布式數(shù)據(jù)流的閉頻繁模式挖掘方法[J]. 計(jì)算機(jī)應(yīng)用研究, 2015, 32(12):3560-3564.
[9] 王有為, 王偉平, 孟丹. 基于統(tǒng)計(jì)方法的 Hive 數(shù)據(jù)倉庫查詢優(yōu)化實(shí)現(xiàn)[J]. 計(jì)算機(jī)研究與發(fā)展, 2015, 52(6): 1452-1462.
[10] 麻雙克, 周蘭鳳. 云計(jì)算環(huán)境下基于優(yōu)先級的 IO 和網(wǎng)絡(luò)密集型應(yīng)用調(diào)度策略[J]. 上海理工大學(xué)學(xué)報(bào), 2017, 39(5): 505-510.
【通聯(lián)編輯:唐一東】