Java線程池

為什么用線程池,在Java中創(chuàng)建線程無(wú)非嗅剖。就是new Thread和實(shí)現(xiàn)Runable接口來(lái)創(chuàng)建線程根蟹,但是這種方法如果不去控制數(shù)量,一味的去new 的話是很損耗系統(tǒng)資源的拷肌。所以對(duì)于線程的優(yōu)化就有了線程池的出現(xiàn)到旦,它是可以把線程歸納到一個(gè)線程池統(tǒng)一管理和使用。

Java線程池的核心就是使用ThreadPoolExecutor類(lèi)看看它的構(gòu)造方法有什么參數(shù)

  public ThreadPoolExecutor(int corePoolSize,  線程池中核心線程數(shù)量
                               int maximumPoolSize, 最大線程數(shù)量
                               long keepAliveTime, 保存活動(dòng)的時(shí)間,不過(guò)它起作用必須在一個(gè)前提下巨缘,就是當(dāng)線程池中的線程數(shù)量超過(guò)了corePoolSize時(shí)添忘,它表示多余的空閑線程的存活時(shí)間,
                               即:多余的空閑線程在超過(guò)keepAliveTime時(shí)間內(nèi)沒(méi)有任務(wù)的話則被銷(xiāo)毀若锁。而這個(gè)主要應(yīng)用在緩存線程池中
                               TimeUnit unit,  表示keepAliveTime的單位搁骑,常用的如:TimeUnit.SECONDS(秒)、TimeUnit.MILLISECONDS(毫秒)
                               BlockingQueue<Runnable> workQueue,  任務(wù)隊(duì)列又固,主要用來(lái)存儲(chǔ)已經(jīng)提交但未被執(zhí)行的任務(wù)仲器,不同的線程池采用的排隊(duì)策略不一樣
                               ThreadFactory threadFactory, 線程工廠,用來(lái)創(chuàng)建線程池中的線程仰冠,通常用默認(rèn)的即可
                               RejectedExecutionHandler handler  通常叫做拒絕策略乏冀,1、在線程池已經(jīng)關(guān)閉的情況下 2洋只、任務(wù)太多導(dǎo)致最大線程數(shù)和任務(wù)隊(duì)列已經(jīng)飽和辆沦,無(wú)法再接收新的任務(wù) 昼捍。在上面兩種情況下,只要滿足其中一種時(shí)肢扯,
                               在使用execute()來(lái)提交新的任務(wù)時(shí)將會(huì)拒絕妒茬,而默認(rèn)的拒絕策略是拋一個(gè)RejectedExecutionException異常
                               ) {

Executors提供五種隊(duì)列對(duì)應(yīng)的Queue類(lèi)型

newFixedThreadPool()--LinkedBlockingQueue
newSingleThreadExecutor()--LinkedBlockingQueue
newCachedThreadPool()--SynchronousQueue
newScheduledThreadPool()--DelayedWorkQueue
newSingleThreadScheduledExecutor()--DelayedWorkQueue

LinkedBlockingQueue:無(wú)界的隊(duì)列
SynchronousQueue:直接提交的隊(duì)列
DelayedWorkQueue:等待隊(duì)列

五種隊(duì)列的作用

  1. newFixedThreadPool() :
    作用:該方法返回一個(gè)固定線程數(shù)量的線程池,該線程池中的線程數(shù)量始終不變蔚晨,即不會(huì)再創(chuàng)建新的線程郊闯,也不會(huì)銷(xiāo)毀已經(jīng)創(chuàng)建好的線程,自始自終都是那幾個(gè)固定的線程在工作蛛株,所以該線程池可以控制線程的最大并發(fā)數(shù)。
    栗子:假如有一個(gè)新任務(wù)提交時(shí)育拨,線程池中如果有空閑的線程則立即使用空閑線程來(lái)處理任務(wù)谨履,如果沒(méi)有,則會(huì)把這個(gè)新任務(wù)存在一個(gè)任務(wù)隊(duì)列中熬丧,一旦有線程空閑了笋粟,則按FIFO方式處理任務(wù)隊(duì)列中的任務(wù)。

  2. newCachedThreadPool() :
    作用:該方法返回一個(gè)可以根據(jù)實(shí)際情況調(diào)整線程池中線程的數(shù)量的線程池析蝴。即該線程池中的線程數(shù)量不確定害捕,是根據(jù)實(shí)際情況動(dòng)態(tài)調(diào)整的。
    栗子:假如該線程池中的所有線程都正在工作闷畸,而此時(shí)有新任務(wù)提交尝盼,那么將會(huì)創(chuàng)建新的線程去處理該任務(wù),而此時(shí)假如之前有一些線程完成了任務(wù)佑菩,現(xiàn)在又有新任務(wù)提交盾沫,那么將不會(huì)創(chuàng)建新線程去處理,而是復(fù)用空閑的線程去處理新任務(wù)殿漠。那么此時(shí)有人有疑問(wèn)了赴精,那這樣來(lái)說(shuō)該線程池的線程豈不是會(huì)越集越多?其實(shí)并不會(huì)绞幌,因?yàn)榫€程池中的線程都有一個(gè)“保持活動(dòng)時(shí)間”的參數(shù)蕾哟,通過(guò)配置它,如果線程池中的空閑線程的空閑時(shí)間超過(guò)該“保存活動(dòng)時(shí)間”則立刻停止該線程莲蜘,而該線程池默認(rèn)的“保持活動(dòng)時(shí)間”為60s谭确。

  3. newSingleThreadExecutor() :
    作用:該方法返回一個(gè)只有一個(gè)線程的線程池,即每次只能執(zhí)行一個(gè)線程任務(wù)菇夸,多余的任務(wù)會(huì)保存到一個(gè)任務(wù)隊(duì)列中琼富,等待這一個(gè)線程空閑,當(dāng)這個(gè)線程空閑了再按FIFO方式順序執(zhí)行任務(wù)隊(duì)列中的任務(wù)庄新。

  4. newScheduledThreadPool() :
    作用:該方法返回一個(gè)可以控制線程池內(nèi)線程定時(shí)或周期性執(zhí)行某任務(wù)的線程池鞠眉。

  5. newSingleThreadScheduledExecutor() :
    作用:該方法返回一個(gè)可以控制線程池內(nèi)線程定時(shí)或周期性執(zhí)行某任務(wù)的線程池薯鼠。只不過(guò)和上面的區(qū)別是該線程池大小為1,而上面的可以指定線程池的大小械蹋。

  • 固定線程數(shù)出皇,如果超過(guò)了設(shè)置的數(shù)量,后續(xù)將不會(huì)繼續(xù)創(chuàng)建線程而是FIFO方式去處理隊(duì)列哗戈。
   ExecutorService executorService = Executors.newFixedThreadPool(3);
          for (int i = 0; i < 10; i++) {
              final int finalI = i;
              executorService.execute(new Runnable() {
                  @Override
                  public void run() {
                      Log.i(TAG, Thread.currentThread().getName() + "   線程正在執(zhí)行第" + finalI + "個(gè)任務(wù)");
                  }
              });
          }
  • 這個(gè)線程池就存在一個(gè)線程實(shí)例郊艘,不管有多少個(gè)都是走隊(duì)列處理
          ExecutorService executorService1 = Executors.newSingleThreadExecutor();
          for (int i = 0; i < 10; i++) {
              final int finalI = i;
              executorService1.execute(new Runnable() {
                  @Override
                  public void run() {
                      Log.i(TAG, Thread.currentThread().getName() + "   線程正在執(zhí)行第" + finalI + "個(gè)任務(wù)");
                  }
              });
          }
  • 這個(gè)會(huì)根據(jù)線池實(shí)際使用情況來(lái)創(chuàng)建線程,數(shù)量不能確定唯咬。
          ExecutorService executorService2 = Executors.newCachedThreadPool();
          for (int i = 0; i < 10; i++) {
              final int finalI = i;
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              executorService2.execute(new Runnable() {
                  @Override
                  public void run() {
                      Log.i(TAG, Thread.currentThread().getName() + "   線程正在執(zhí)行第" + finalI + "個(gè)任務(wù)");
                      try {
                          Thread.sleep(finalI *500);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              });
          }
  • 可以定時(shí)的隊(duì)列
          ScheduledExecutorService scheduledExecutorService = Executors
                  .newScheduledThreadPool(3);
          scheduledExecutorService.schedule(new Runnable() {
              @Override
              public void run() {
                  Log.i(TAG, Thread.currentThread().getName());
              }
          }, 1, TimeUnit.MILLISECONDS);

          ScheduledExecutorService scheduledExecutorService4 = Executors
                  .newScheduledThreadPool(3);
          scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
              @Override
              public void run() {
                  Log.i(TAG, Thread.currentThread().getName() );
              }
          },1,2, TimeUnit.MILLISECONDS);

          ScheduledExecutorService scheduledExecutorService3 = Executors
                  .newSingleThreadScheduledExecutor();
          scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
              @Override
              public void run() {
                  Log.i(TAG, Thread.currentThread().getName() );
              }
          },1,2,TimeUnit.SECONDS);

優(yōu)化線程池ThreadPoolExecutor

雖說(shuō)線程池極大改善了系統(tǒng)的性能纱注,不過(guò)創(chuàng)建線程池也是需要資源的,所以線程池內(nèi)線程數(shù)量的大小也會(huì)影響系統(tǒng)的性能胆胰,大了反而浪費(fèi)資源狞贱,小了反而影響系統(tǒng)的吞吐量,所以我們創(chuàng)建線程池需要把握一個(gè)度才能合理的發(fā)揮它的優(yōu)點(diǎn)蜀涨,通常來(lái)說(shuō)我們要考慮的因素有CPU的數(shù)量瞎嬉、內(nèi)存的大小、并發(fā)請(qǐng)求的數(shù)量等因素厚柳,按需調(diào)整氧枣。 通常核心線程數(shù)可以設(shè)為CPU數(shù)量+1,而最大線程數(shù)可以設(shè)為CPU的數(shù)量*2+1别垮。獲取CPU數(shù)量的方法為:

   Runtime.getRuntime().availableProcessors();

shutdown()和shutdownNow()的區(qū)別

關(guān)于線程池的停止便监,ExecutorService為我們提供了兩個(gè)方法:shutdown和shutdownNow,這兩個(gè)方法各有不同碳想,可以根據(jù)實(shí)際需求方便的運(yùn)用茬贵,如下:

1.shutdown()方法在終止前允許執(zhí)行以前提交的任務(wù)。
2.shutdownNow()方法則是阻止正在任務(wù)隊(duì)列中等待任務(wù)的啟動(dòng)并試圖停止當(dāng)前正在執(zhí)行的任務(wù)移袍。

http://blog.csdn.net/u010687392/article/details/49850803

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末解藻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子葡盗,更是在濱河造成了極大的恐慌螟左,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,222評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件觅够,死亡現(xiàn)場(chǎng)離奇詭異胶背,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)喘先,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)钳吟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人窘拯,你說(shuō)我怎么就攤上這事红且“泳ィ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,720評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵暇番,是天一觀的道長(zhǎng)嗤放。 經(jīng)常有香客問(wèn)我,道長(zhǎng)壁酬,這世上最難降的妖魔是什么次酌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,568評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮舆乔,結(jié)果婚禮上岳服,老公的妹妹穿的比我還像新娘。我一直安慰自己希俩,他們只是感情好派阱,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著斜纪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪文兑。 梳的紋絲不亂的頭發(fā)上盒刚,一...
    開(kāi)封第一講書(shū)人閱讀 49,879評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音绿贞,去河邊找鬼因块。 笑死,一個(gè)胖子當(dāng)著我的面吹牛籍铁,可吹牛的內(nèi)容都是我干的涡上。 我是一名探鬼主播,決...
    沈念sama閱讀 39,028評(píng)論 3 409
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拒名,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吩愧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起增显,我...
    開(kāi)封第一講書(shū)人閱讀 37,773評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤雁佳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后同云,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體糖权,經(jīng)...
    沈念sama閱讀 44,220評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評(píng)論 2 327
  • 正文 我和宋清朗相戀三年炸站,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了星澳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,697評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡旱易,死狀恐怖禁偎,靈堂內(nèi)的尸體忽然破棺而出腿堤,到底是詐尸還是另有隱情,我是刑警寧澤届垫,帶...
    沈念sama閱讀 34,360評(píng)論 4 332
  • 正文 年R本政府宣布释液,位于F島的核電站,受9級(jí)特大地震影響装处,放射性物質(zhì)發(fā)生泄漏误债。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評(píng)論 3 315
  • 文/蒙蒙 一妄迁、第九天 我趴在偏房一處隱蔽的房頂上張望寝蹈。 院中可真熱鬧,春花似錦登淘、人聲如沸箫老。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,782評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)耍鬓。三九已至,卻和暖如春流妻,著一層夾襖步出監(jiān)牢的瞬間牲蜀,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,010評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工绅这, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涣达,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,433評(píng)論 2 360
  • 正文 我出身青樓证薇,卻偏偏與公主長(zhǎng)得像度苔,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浑度,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容