Android 多線程 線程池原理 封裝線程池__線程

來源:互聯網
上載者:User

我自己理解看來。線程池顧名思義就是一個容器的意思,需要注意的是,每一個線程都是需要CPU分配資源去執行的。如果由於總是new Thread()開啟一個線程,那麼就會大量的消耗CPU的資源,導致Android運行變慢,甚至OOM(out of memory),因而Java就出現了一個ThreadPoolExecutor來管理這些線程。控制最多的線程數maximumPoolSize,核心線程數corePoolSize,來管理我們需要開啟的線程數。這樣減少了建立和銷毀線程的次數,每個背景工作執行緒都可以被重複利用,可執行多個任務。所以,我們就可以根據手機的CPU核心數來控制App可以開的最大線程數,保證程式的合理運行。 
在Android中當同時並發多個網路線程時,引入線程池技術會極大地提高APP的效能。例如:多線程下載,點一個下載一個(假設允許最多同時下載五個),當點到第六個的時候開始等待,這就涉及到線程的管理。 
Android引入線程池好處是:提升了效能(建立和消耗對象費時費CPU資源);防止記憶體過度消耗(控制活動線程的數量,防止並發線程過多)。 1.ThreadPoolExecutor 1.ThreadPoolExecutor參數

jdk自身帶有線程池的實作類別ThreadPoolExecutor,使用ThreadPoolExecutor,瞭解其每個參數的意義是必不可少的。 
ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler) 
corePoolSize: 核心線程數,能夠同時執行的任務數量; 
maximumPoolSize:除去緩衝隊列中等待的任務,最大能容納的任務數(其實是包括了核心線程池數量); 
keepAliveTime:超出workQueue的等待任務的存活時間,就是指maximumPoolSize裡面的等待任務的存活時間; 
unit:時間單位; 
workQueue:阻塞等待線程的隊列,一般使用new LinkedBlockingQueue()這個,如果不指定容量,會一直往裡邊添加,沒有限制,workQueue永遠不會滿; 
threadFactory:建立線程的工廠,使用系統預設的類; 
handler:當任務數超過maximumPoolSize時,對任務的處理策略,預設策略是拒絕添加; 2.阻塞隊列

隊列用於排隊,避免一瞬間出現大量請求的問題。 
阻塞隊列分為 有限隊列(SynchronousQueue、ArrayBlockingQueue)和 無限隊列(LinkedBloackingQueue)。 3.執行流程

當線程數小於corePoolSize時,每添加一個任務,則立即開啟線程執行;當corePoolSize滿的時候,後面添加的任務將放入緩衝隊列workQueue等待;當workQueue也滿的時候,看是否超過maximumPoolSize線程數,如果超過,預設拒絕執行。 
下面我們看個例子:假如corePoolSize=2,maximumPoolSize=3,workQueue容量為8;最開始,執行的任務A,B,此時corePoolSize已用完,再次執行任務C,則C將被放入緩衝隊列workQueue中等待著,如果後來又添加了7個任務,此時workQueue已滿,則後面再來的任務將會和maximumPoolSize比較,由於maximumPoolSize為3,所以只能容納1個了,因為有2個在corePoolSize中運行了,所以後面來的任務預設都會被拒絕。 4.終止一個線程

我們編寫終止一個線程的 junit 測試方法:

private class MyRunnable implements Runnable {    public volatile boolean flag = true;    @Override    public void run() {        while (flag && !Thread.interrupted()) {            try {                System.out.println("running");                Thread.sleep(500);            } catch (InterruptedException e) {                e.printStackTrace();                return; //2.中斷線程時, 注意此處必須做處理            }        }    }}@Testpublic void RunnableTest() throws InterruptedException {    MyRunnable runnable = new MyRunnable();    Thread thread = new Thread(runnable);    thread.start();    Thread.sleep(2000);    runnable.flag = true;    thread.interrupt(); //1.中斷線程}
2.封裝線程池管理者

下面我們基於ThreadPoolExecutor對線程池進行封裝:

/** * 線程池管理 管理整個項目中所有的線程,所以不能有多個執行個體對象 */public class ThreadPoolManager {    /**     * 單例設計模式(餓漢式)     *  單例首先私人化構造方法,然後餓漢式一開始就開始建立,並提供get方法     */    private static ThreadPoolManager mInstance = new ThreadPoolManager();    public static ThreadPoolManager getInstance() {        return mInstance;    }    private int corePoolSize;//核心線程池的數量,同時能夠執行的線程數量    private int maximumPoolSize;//最大線程池數量,表示當緩衝隊列滿的時候能繼續容納的等待任務的數量    private long keepAliveTime = 1;//存活時間    private TimeUnit unit = TimeUnit.HOURS;    private ThreadPoolExecutor executor;    private ThreadPoolManager() {        /**         * 給corePoolSize賦值:當前裝置可用處理器核心數*2 + 1,能夠讓cpu的效率得到最大程度執行(有研究論證的)         */        corePoolSize = Runtime.getRuntime().availableProcessors()*2+1;        maximumPoolSize = corePoolSize; //雖然maximumPoolSize用不到,但是需要賦值,否則報錯        executor = new ThreadPoolExecutor(                corePoolSize, //當某個核心任務執行完畢,會依次從緩衝隊列中取出等待任務                maximumPoolSize, //5,先corePoolSize,然後new LinkedBlockingQueue<Runnable>(),然後maximumPoolSize,但是它的數量是包含了corePoolSize的                keepAliveTime, //表示的是maximumPoolSize當中等待任務的存活時間                unit,                 new LinkedBlockingQueue<Runnable>(), //緩衝隊列,用於存放等待任務,Linked的先進先出                Executors.defaultThreadFactory(), //建立線程的工廠                new ThreadPoolExecutor.AbortPolicy() //用來對超出maximumPoolSize的任務的處理策略                );    }    /**     * 執行任務     */    public void execute(Runnable runnable){        if(runnable==null)return;        executor.execute(runnable);    }    /**     * 從線程池中移除任務     */    public void remove(Runnable runnable){        if(runnable==null)return;        executor.remove(runnable);    }}
其中,擷取當前可用的處理器核心數我們用Runtime.getRuntime().availableProcessors(),我們來看它的注釋:

下面我們來看一下Runnable與線程的區別: 
Runnable只是一個介面,它的源碼如下,而線程是真正開啟系統資源去執行任務,他們兩個,線程是真正消耗系統資源的

/** * Represents a command that can be executed. Often used to run code in a * different {@link Thread}. */public interface Runnable {    /**     * Starts executing the active part of the class' code. This method is     * called when a thread is started that has been created with a class which     * implements {@code Runnable}.     */    public void run();}

到這裡已經基本上介紹完了線程池,下面我們通過實際編碼看一下如何使用線程池。 3.示範線程池的使用方法

下面是一個線程池的例子(示範多線程執行任務),以加深對原理的理解 
1.引入我們封裝好的ThreadPoolManager.java 
2.示範功能

/** * 示範線程池 */public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        /**         * 建立九個任務         */        for (int i = 0; i < 9; i++) {            ThreadPoolManager.getInstance().execute(new DownloadTask(i));        }    }    /**     * 模仿下載任務,實現Runnable     */    class DownloadTask implements Runnable{        private int num;        public DownloadTask(int num) {            super();            this.num = num;            Log.d("JAVA", "task - "+num + " 等待中...");        }        @Override        public void run() {            Log.d("JAVA", "task - "+num + " 開始執行了...開始執行了...");            SystemClock.sleep(5000); //類比延時執行的時間            Log.e("JAVA", "task - "+num + " 結束了...");        }    }}
列印結果如下:



轉載:http://blog.csdn.net/smartbetter/article/details/52056272

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.