- 通過(guò)Process.setThreadPriority()方法來(lái)設(shè)置線程使用的是后臺(tái)運(yùn)行優(yōu)先級(jí)矛物。 這個(gè)方法減少了通過(guò)Runnable創(chuàng)建的線程和和UI線程之間的資源競(jìng)爭(zhēng)。
-
你還應(yīng)該通過(guò)在Runnable 自身中調(diào)用Thread.currentThread()來(lái)存儲(chǔ)一個(gè)引用到Runnable對(duì)象的線程跪但。
class PhotoDecodeRunnable implements Runnable {
// 定義要在這個(gè)任務(wù)中執(zhí)行的代碼
@Override
public void run() {
// 把當(dāng)前的線程變成后臺(tái)執(zhí)行的線程
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
...
//在PhotoTask實(shí)例中存儲(chǔ)當(dāng)前線程履羞,以至于這個(gè)實(shí)例能中斷這個(gè)線程
mPhotoTask.setImageDecodeThread(Thread.currentThread());
...
}
} -
創(chuàng)建多線程管理器
-
為線程池使用靜態(tài)變量
為了有一個(gè)單一控制點(diǎn)用來(lái)限制CPU或涉及網(wǎng)絡(luò)資源的Runnable類型,你可能需要有一個(gè)能管理所有線程的線程池屡久,且每個(gè)線程都會(huì)是單個(gè)實(shí)例忆首。比如,你可以把這個(gè)作為一部分添加到你的全局變量的聲明中去:
public class PhotoManager {
...
static {
...
// Creates a single static instance of PhotoManager
sInstance = new PhotoManager();
}
...
-
為線程池使用靜態(tài)變量
*** 使用私有構(gòu)造方法***
讓構(gòu)造方法私有從而保證這是一個(gè)單例被环,這意味著你不需要在同步代碼塊(synchronized block)中額外訪問這個(gè)類:
public class PhotoManager {
...
* Constructs the work queues and thread pools used to download
* and decode images. Because the constructor is marked private,
* it's unavailable to other classes, even in the same package.
*/
private PhotoManager() {
...
}通過(guò)調(diào)用線程池類里的方法開啟你的任務(wù)
在線程池類中定義一個(gè)能添加任務(wù)到線程池隊(duì)列的方法糙及。例如:
public class PhotoManager {
...
// Called by the PhotoView to get a photo
static public PhotoTask startDownload(
PhotoView imageView,
boolean cacheFlag) {
...
// Adds a download task to the thread pool for execution
sInstance.
mDownloadThreadPool.
execute(downloadTask.getHTTPDownloadRunnable());
...
}在構(gòu)造方法中實(shí)例化一個(gè)Handler,且將它附加到你APP的UI線程筛欢。
一個(gè)Handler允許你的APP安全地調(diào)用UI對(duì)象(例如 View對(duì)象)的方法浸锨。大多數(shù)UI對(duì)象只能從UI線程安全的代碼中被修改。這個(gè)方法將會(huì)在與UI線程進(jìn)行通信(Communicate with the UI Thread)這一課中進(jìn)行詳細(xì)的描述悴能。例如:
private PhotoManager() {
...
// Defines a Handler object that's attached to the UI thread
mHandler = new Handler(Looper.getMainLooper()) {
/*
* handleMessage() defines the operations to perform when
* the Handler receives a new Message to process.
*/
@Override
public void handleMessage(Message inputMessage) {
...
}
...
}
}
-
確定線程池的參數(shù)
一旦有了整體的類結(jié)構(gòu),你可以開始定義線程池了揣钦。為了初始化一個(gè)ThreadPoolExecutor對(duì)象,你需要提供以下數(shù)值:-
線程池的初始化大小和最大的大小
這個(gè)是指最初分配給線程池的線程數(shù)量漠酿,以及線程池中允許的最大線程數(shù)量冯凹。在線程池中擁有的線程數(shù)量主要取決于你的設(shè)備的CPU內(nèi)核數(shù)。
這個(gè)數(shù)字可以從系統(tǒng)環(huán)境中獲得:
public class PhotoManager {
...
/*
* Gets the number of available cores
* (not always the same as the maximum number of cores)
*/
private static int NUMBER_OF_CORES =Runtime.getRuntime().availableProcessors();
}
這個(gè)數(shù)字可能并不反映設(shè)備的物理核心數(shù)量,因?yàn)橐恍┰O(shè)備根據(jù)系統(tǒng)負(fù)載關(guān)閉了一個(gè)或多個(gè)CPU內(nèi)核宇姚,對(duì)于這樣的設(shè)備匈庭,availableProcessors()方法返回的是處于活動(dòng)狀態(tài)的內(nèi)核數(shù)量,可能少于設(shè)備的實(shí)際內(nèi)核總數(shù)浑劳。
-
線程池的初始化大小和最大的大小
-
線程保持活動(dòng)狀態(tài)的持續(xù)時(shí)間和時(shí)間單位
這個(gè)是指線程被關(guān)閉前保持空閑狀態(tài)的持續(xù)時(shí)間阱持。這個(gè)持續(xù)時(shí)間通過(guò)時(shí)間單位值進(jìn)行解譯,是TimeUnit()中定義的常量之一魔熏。 -
一個(gè)任務(wù)隊(duì)列
這個(gè)傳入的隊(duì)列由ThreadPoolExecutor獲取的Runnable對(duì)象組成衷咽。為了執(zhí)行一個(gè)線程中的代碼,一個(gè)線程池管理者從先進(jìn)先出的隊(duì)列中取出一個(gè)Runnable對(duì)象且把它附加到一個(gè)線程蒜绽。當(dāng)你創(chuàng)建線程池時(shí)需要提供一個(gè)隊(duì)列對(duì)象镶骗,這個(gè)隊(duì)列對(duì)象類必須實(shí)現(xiàn)BlockingQueue接口。為了滿足你的APP的需求躲雅,你可以選擇一個(gè)Android SDK中已經(jīng)存在的隊(duì)列實(shí)現(xiàn)類鼎姊。為了學(xué)習(xí)更多相關(guān)的知識(shí),你可以看一下ThreadPoolExecutor類的概述相赁。下面是一個(gè)使用LinkedBlockingQueue實(shí)現(xiàn)的例子:
public class PhotoManager {
...
private PhotoManager() {
...
// A queue of Runnables
private final BlockingQueue<Runnable> mDecodeWorkQueue;
...
// Instantiates the queue of Runnables as a LinkedBlockingQueue
mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();
...
}
...
}
創(chuàng)建一個(gè)線程池
為了創(chuàng)建一個(gè)線程池相寇,可以通過(guò)調(diào)用[ThreadPoolExecutor()](http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html#ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>))構(gòu)造方法初始化一個(gè)線程池管理者對(duì)象,這樣就能創(chuàng)建和管理一組可約束的線程了钮科。如果線程池的初始化大小和最大大小相同唤衫,ThreadPoolExecutor在實(shí)例化的時(shí)候就會(huì)創(chuàng)建所有的線程對(duì)象。例如:
private PhotoManager() {
...
// Sets the amount of time an idle thread waits before terminating
private static final int KEEP_ALIVE_TIME = 1;
// Sets the Time Unit to seconds
private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
// Creates a thread pool manager
mDecodeThreadPool = new ThreadPoolExecutor(
NUMBER_OF_CORES, // Initial pool size
NUMBER_OF_CORES, // Max pool size
KEEP_ALIVE_TIME,
KEEP_ALIVE_TIME_UNIT,
mDecodeWorkQueue);
}