JAVA線程池詳解

1、在什麼情況下使用線程池?       

 

1.單個任務處理的時間比較短     

2.將需處理的任務的數量大

 

2、使用線程池的好處

 

1.減少在創建和銷燬線程上所花的時間以及系統資源的開銷     

2.如不使用線程池,有可能造成系統創建大量線程而導致消耗完系統內存以及”過度切換”。

 

3、JDK自帶線程池總類介紹

 

1、newFixedThreadPool創建一個指定工作線程數量的線程池。每當提交一個任務就創建一個工作線程,如果工作線程數量達到線程池初始的最大數,則將提交的任務存入到池隊列中。       

2、newCachedThreadPool創建一個可緩存的線程池。這種類型的線程池特點是:      

     1).工作線程的創建數量幾乎沒有限制(其實也有限制的,數目爲Interger. MAX_VALUE), 這樣可靈活的往線程池中添加線程。      

     2).如果長時間沒有往線程池中提交任務,即如果工作線程空閒了指定的時間(默認爲1分鐘),則該工作線程將自動終止。終止後,如果你又提交了新的任務,則線程池重新創建一個工作線程。       

3、newSingleThreadExecutor創建一個單線程化的Executor,即只創建唯一的工作者線程來執行任務,如果這個線程異常結束,會有另一個取代它,保證順序執行(我覺得這點是它的特色)。單工作線程最大的特點是可保證順序地執行各個任務,並且在任意給定的時間不會有多個線程是活動的 。       

4、newScheduleThreadPool創建一個定長的線程池,而且支持定時的以及週期性的任務執行,類似於Timer。(這種線程池原理暫還沒完全瞭解透徹) 

總結: 一.FixedThreadPool是一個典型且優秀的線程池,它具有線程池提高程序效率和節省創建線程時所耗的開銷的優點。但是,在線程池 空閒時,即線程池中沒有可運行任務時,它不會釋放工作線程,還會佔用一定的系統資源。         

              二.CachedThreadPool的特點就是在線程池空閒時,即線程池中沒有可運行任務時,它會釋放工作線程,從而釋放工作線程所佔用的資源。但是,但當出現新任務時,又要創建一新的工作線程,又要一定的系統開銷。並且,在使用CachedThreadPool時,一定要注意控制任務的數量,否則,由於大量線程同時運行,很有會造成系統癱瘓。

4、代碼詳解

 

package com.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * java 線程池學習
 */
public class ThreadPoolTest {
    /**
    * 線程池的概念
    * jdk5提出了ThreadPool的概念
    * 之所以採用線程池的主要原因在於:
    * 線程時間=T1(創建時間)+T2(運行時間)+T3(銷燬時間)
    * 線程池則可以一個線程空閒下來後爲另一個服務,這樣子,就達到了整體的效果,
    * 嘿嘿(敏捷團隊的每一個人一樣)
    *
    * 四種種靜態工廠線程池
    *
    * 固定線程池
    * 緩存線程池
    * 單一線程池 (採用替補的方式)
    * 另外,還有定時器的線程池 (使用可以參考Timer的使用)
    */

    public static void main(String[] args) {
        /**
        * 測試實例說明
        * 有100個任務,一次提交給線程池10個,分析線程池,每次的處理情況
        */


        //固定的線程池
//        ExecutorService threadPool = Executors.newFixedThreadPool(3);            //Executor是一個工具類,聲明瞭一個具有三個線程的線程池


        //緩存的線程池 ,根據任務量自動增加線程數量,和回收 ,就會自動增加到十個線程
//         ExecutorService threadPool = Executors.newCachedThreadPool();


        //線程池中只有一個線程,但是線程死了後可以對另一個線程調用重新啓動,(單線程池)
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 0;i<10;i++){
            final int finalI = i;
            threadPool.execute(new Runnable() {            //任務執行
                @Override
                public void run() {
                    for(int j = 0;j<10;j++){
                        try {
                            Thread.sleep(20);                 //便於輸出觀看
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+" loop of " + finalI +
                        " for task of "+ j);     //某個線程正在進行第幾次循環
                    }
                }
            });
        }
        System.out.println("all of 10 tasks have committed");
//        threadPool.shutdown();


        //採用定時任務,定時器任務類型
        Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("bombing");
            }
        },5,2, TimeUnit.SECONDS);   //5秒之後炸,每個2秒炸一下  ,schedule(定時任務)或者schedule之後定時,最後一個是單位
    }
}

/**分析
* 真正的線程接口是ExecutorService,而Executor是一個頂級的接口。
* 線程池的編程模式下,任務是提交給整個池子,由池子來負責分配任務;相當於,先接手(接受任務防止長時間的等待),接手後進行細節分配。
* 任務是提交給線程池的,但是一個線程只能執行一個任務,但是可以同時向線程池提交多個任務。
*
* 但是對於高端的使用,需要自己定製線程池
*/

比較:

ExecutorService

真正的線程池接口。

ScheduledExecutorService

能和Timer/TimerTask類似,解決那些需要任務重複執行的問題。

ThreadPoolExecutor

ExecutorService的默認實現。

ScheduledThreadPoolExecutor

繼承ThreadPoolExecutor的ScheduledExecutorService接口實現,週期性任務調度的類實現。

 

5、用途及用法

 

網絡請求通常有兩種形式:第一種,請求不是很頻繁,而且每次連接後會保持相當一段時間來讀數據或者寫數據,最後斷開,如文件下載,網絡流媒體等。另一種形式是請求頻繁,但是連接上以後讀/寫很少量的數據就斷開連接。考慮到服務的併發問題,如果每個請求來到以後服務都爲它啓動一個線程,那麼這對服務的資源可能會造成很大的浪費

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章