目标:掌握多線程的使用及應用場景
- 怎麼使用多線程
// 盡量不要如此使用 new Thread(new Runnable() { @Override public void run() { } }).start(); // 通過線程池友善管理 Executor executor = Executors.newCachedThreadPool(); executor.execute(runnable);
-
程序和線程的差別
其實沒有可比性,之是以大家喜歡用來比較是因為他們都可以并行,兩個程序可以并行,兩個線程也可以并行,是以大家喜歡用來對比。
但其實差别還是比較大的,程序在作業系統中是擁有獨立空間的,并且程序間是不共享的,而一個程序中可能會包含很多個線程,而線程間是可以共享資源。
-
CPU線程與作業系統的線程怎麼了解
CPU線程就是我們平時聽到的幾核CPU的概念,比如6核的CPU,它的CPU線程就是6,它表示CPU同時隻能幹六件事,而我們代碼中所開的線程其實是作業系統的線程,作業系統通過時間分片可以将線程開的很多很多。
-
ThreadPoolExecutor
以ThreadPoolExecutor為例,他的構造函數裡面會有幾個重要的參數:
-
第一個參數corePoolSize表示該線程池需要保留的線程數量,即使在空閑的時候。
maximumPoolSize表示目前線程池最大可以擁有多少個線程,當線程池中開到最大,并且所有線程都在執行任務,此時如果有任務來了,就需要等待線程池中有空閑的線程釋放出來。
keepAliveTime表示當線程池中超過corePoolSize的部分,在空閑狀态時可以繼續保留的時間,一旦超過這個時間就會銷毀。
timeUnit表示上面參數的時間機關
workQueue顯然就是線程池正在滿池運作,新的待執行任務需要放在這個隊列裡等待空閑線程的到來。
-
newFixedThreadPool(int nThreads)
這個方法是用來創在保持特定數量的線程池,因為這個數量是既是線程池的最大線程數,也是線程池需要保留的線程數,是以,線程也不好增加,在空閑狀态時也不能回收多餘的。
是以它的應用場景也是比較少的,一般是用來集中處理一些爆發性的事物後立即釋放,比如突然來了20張圖檔要處理,這個時候肯定不能一張一張的處理,可以開多線程并行處理,如下所示:
List<Bitmap> imgs = somewhereGetImgs(20); ExecutorService executor = Executors.newFixedThreadPool(20); for(Bitmap bitmap: imgs) { // 向線程池中扔了20個任務同時執行 executor.execute(processImgRunnable); } // 執行完就快速的回收 executor.shutdown();
-
Callable
有傳回值的Runnable。
舉個例子:
-
既然要放到異步線程裡去執行,那傳回結果又有什麼意義呢,難道要阻塞主線程一直等任務線程執行完?
上面的例子就說明了部分使用場景,我們可以先拿到一個future的執行個體來在後面進行判斷是否任務執行完了(當然,不一定是上面死循環的方式),實際可以根據具體業務來做。