av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

Java線程池的那些事

熟悉java多線程的 朋友一定十分了解java的線程池,jdk中的核心實(shí)現(xiàn)類為java.util.concurrent.ThreadPoolExecutor。大家可能 了解到它的原理,甚至看過它的源碼;但是就像我一樣,大家可能對(duì)它的作用存在誤解?,F(xiàn)在問題來了,jdk為什么要提供java線程池?使用java線程池 對(duì)于每次都創(chuàng)建一個(gè)新Thread有什么優(yōu)勢(shì)?

創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),臨川企業(yè)網(wǎng)站建設(shè),臨川品牌網(wǎng)站建設(shè),網(wǎng)站定制,臨川網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,臨川網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

十年的長安網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都營銷網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整長安建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“長安網(wǎng)站設(shè)計(jì)”,“長安網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

對(duì)線程池的誤解

很長一段時(shí)間里我一直以為java線程池是為了提高多線程下創(chuàng)建線程的效率。創(chuàng)建好一些線程并緩存在線程池里,后面來了請(qǐng)求(Runnable)就 從連接池中取出一個(gè)線程處理請(qǐng)求;這樣就避免了每次創(chuàng)建一個(gè)新Thread對(duì)象。直到前段時(shí)間我看到一篇Neal Gafter(和Joshua Bloch合著了《Java Puzzlers》,現(xiàn)任職于微軟,主要從事.NET語言方面的工作)的訪談,里面有這么一段談話(http://www.infoq.com/cn/articles/neal-gafter-on-java):

乍一看,大神的思路就是不一樣:java線程池是為了防止java線程占用太多資源?

雖然是java大神的訪談,但是也不能什么都信,你說占資源就占資源?還是得寫測(cè)試用例測(cè)一下。

首先驗(yàn)證下我的理解:

java線程池和創(chuàng)建java線程哪個(gè)效率高?

直接上測(cè)試用例:

  
 
  1. public class ThreadPoolTest extends TestCase { 
  2.     private static final int COUNT = 10000; 
  3.  
  4.     public void testThreadPool() throws InterruptedException { 
  5.         CountDownLatch countDownLatch = new CountDownLatch(COUNT); 
  6.         ExecutorService executorService = Executors.newFixedThreadPool(100); 
  7.         long bg = System.currentTimeMillis(); 
  8.         for (int i = 0; i < COUNT; i++) { 
  9.     Runnable command = new TestRunnable(countDownLatch); 
  10.     executorService.execute(command); 
  11.         } 
  12.         countDownLatch.await(); 
  13.         System.out.println("testThreadPool:" + (System.currentTimeMillis() - bg)); 
  14.     } 
  15.  
  16.     public void testNewThread() throws InterruptedException { 
  17.         CountDownLatch countDownLatch = new CountDownLatch(COUNT); 
  18.         long bg = System.currentTimeMillis(); 
  19.         for (int i = 0; i < COUNT; i++) { 
  20.     Runnable command = new TestRunnable(countDownLatch); 
  21.     Thread thread = new Thread(command); 
  22.     thread.start(); 
  23.         } 
  24.         countDownLatch.await(); 
  25.         System.out.println("testNewThread:" + (System.currentTimeMillis() - bg)); 
  26.     } 
  27.  
  28.     private static class TestRunnable implements Runnable { 
  29.         private final CountDownLatch countDownLatch; 
  30.  
  31.         TestRunnable(CountDownLatch countDownLatch) { 
  32.     this.countDownLatch = countDownLatch; 
  33.         } 
  34.  
  35.         @Override 
  36.         public void run() { 
  37.     countDownLatch.countDown(); 
  38.         } 
  39.     } 

這里使用Executors.newFixedThreadPool(100)是為了控制線程池的核心連接數(shù)和***連接數(shù)一樣大,都為100。

我的機(jī)子上的測(cè)試結(jié)果:

testThreadPool:31
testNewThread:624

可以看到,使用線程池處理10000個(gè)請(qǐng)求的處理時(shí)間為31ms,而每次啟用新線程的處理時(shí)間為624ms。

好了,使用線程池確實(shí)要比每次都創(chuàng)建新線程要快一些;但是testNewThread一共耗時(shí)624ms,算下平均每次請(qǐng)求的耗時(shí)為:

624ms/10000=62.4us

每次創(chuàng)建并啟動(dòng)線程的時(shí)間為62.4微秒。根據(jù)80/20原理,這點(diǎn)兒時(shí)間根本可以忽略不計(jì)。所以線程池并不是為了效率設(shè)計(jì)的。

java線程池是為了節(jié)約資源?

再上測(cè)試用例:

  
 
  1. public class ThreadPoolTest extends TestCase { 
  2.     public void testThread() throws InterruptedException { 
  3.         int i = 1; 
  4.         while (true) { 
  5.     Runnable command = new TestRunnable(); 
  6.     Thread thread = new Thread(command); 
  7.     thread.start(); 
  8.     System.out.println(i++); 
  9.         } 
  10.     } 
  11.  
  12.     private static class TestRunnable implements Runnable { 
  13.         @Override 
  14.         public void run() { 
  15.     try { 
  16.         Thread.sleep(1000); 
  17.     } catch (InterruptedException e) { 
  18.         e.printStackTrace(); 
  19.     } 
  20.         } 
  21.     } 

以上用例模擬每次請(qǐng)求都創(chuàng)建一個(gè)新線程處理請(qǐng)求,然后默認(rèn)每個(gè)請(qǐng)求的處理時(shí)間為1000ms。而在我的機(jī)子上當(dāng)請(qǐng)求數(shù)達(dá)到1096時(shí)會(huì)內(nèi)存溢出:

java.lang.OutOfMemoryError: unable to create new native thread

為什么會(huì)拋OOM Error呢?因?yàn)閖vm會(huì)為每個(gè)線程分配一定內(nèi)存(JDK5.0以后每個(gè)線程堆棧大小為1M,以前每個(gè)線程堆棧大小為256K,也可以通過jvm參數(shù)-Xss來設(shè)置),所以當(dāng)線程數(shù)達(dá)到一定數(shù)量時(shí)就報(bào)了該error。

設(shè)想如果不使用java線程池,而為每個(gè)請(qǐng)求都創(chuàng)建一個(gè)新線程來處理該請(qǐng)求,當(dāng)請(qǐng)求量達(dá)到一定數(shù)量時(shí)一定會(huì)內(nèi)存溢出的;而我們使用java線程池的話,線程數(shù)量一定會(huì)<=maximumPoolSize(線程池的***線程數(shù)),所以設(shè)置合理的話就不會(huì)造成內(nèi)存溢出。

現(xiàn)在問題明朗了:java線程池是為了防止內(nèi)存溢出,而不是為了加快效率。

淺談java線程池

上文介紹了java線程池啟動(dòng)太多會(huì)造成OOM,使用java線程池也應(yīng)該設(shè)置合理的線程數(shù)數(shù)量;否則應(yīng)用可能十分不穩(wěn)定。然而該如何設(shè)置這個(gè)數(shù)量呢?我們可以通過這個(gè)公式來計(jì)算:

(MaxProcessMemory – JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Max number of threads

  • MaxProcessMemory     進(jìn)程***的內(nèi)存

  • JVMMemory                 JVM內(nèi)存

  • ReservedOsMemory     JVM的本地內(nèi)存

  • ThreadStackSize            線程棧的大小

MaxProcessMemory

MaxProcessMemory:進(jìn)程***的尋址空間,當(dāng)然也不能超過虛擬內(nèi)存和物理內(nèi)存的總和。關(guān)于不同系統(tǒng)的進(jìn)程可尋址的***空間,可參考下面表格:

Maximum Address Space Per Process

Operating System

Maximum Address Space Per Process

Redhat Linux 32 bit

2 GB

Redhat Linux 64 bit

3 GB

Windows 98/2000/NT/Me/XP

2 GB

Solaris x86 (32 bit)

4 GB

Solaris 32 bit

4 GB

Solaris 64 bit

Terabytes

JVMMemory

JVMMemory: Heap + PermGen,即堆內(nèi)存和***代內(nèi)存和(注意,不包括本地內(nèi)存)。

ReservedOsMemory

ReservedOSMemory:Native heap,即JNI調(diào)用方法所占用的內(nèi)存。

ThreadStackSize

ThreadStackSize:線程棧的大小,JDK5.0以后每個(gè)線程堆棧大小默認(rèn)為1M,以前每個(gè)線程堆棧大小為256K;可以通過jvm參數(shù)-Xss來設(shè)置;注意-Xss是jvm的非標(biāo)準(zhǔn)參數(shù),不強(qiáng)制所有平臺(tái)的jvm都支持。

如何調(diào)大線程數(shù)?

如果程序需要大量的線程,現(xiàn)有的設(shè)置不能達(dá)到要求,那么可以通過修改MaxProcessMemory,JVMMemory,ThreadStackSize這三個(gè)因素,來增加能創(chuàng)建的線程數(shù):

  • MaxProcessMemory 使用64位操作系統(tǒng)

  • JVMMemory   減少JVMMemory的分配

  • ThreadStackSize  減小單個(gè)線程的棧大小


分享名稱:Java線程池的那些事
文章起源:http://uogjgqi.cn/article/codhhjs.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流