android中關於對執行緒池的理解以及操作
在android中很多時候我們需要處理一些比較耗時的操作,而在android中明確的規定主執行緒不能進行一些耗時的操作,如果要進行一些耗時的操作,那麼就必須要開啟子執行緒去處理。那麼問題就來了。是否我們可以不斷地去new出子執行緒呢?答案是否定的。因為這樣子會造成系統的資源消耗過大。因此我們要想解決這個問題就需要引入一個執行緒池的概念。
所謂的執行緒池,我們可以通過一個簡單的案例來理解。某天你突然發現你的錢包的錢不夠用了,那怎麼辦?去銀行取唄!這時我們可以將某某銀行比作一個執行緒池。銀行裡面肯定有為群眾辦理業務的視窗,這些視窗我們就可以比作是執行緒。一個銀行不可能有無數個辦理業務的視窗,都有一個最大數值。假設某某銀行這裡面一共有20個辦理業務的視窗,也就是說最多它只能有20個視窗去辦理業務,不可能超過20.這個我們就可以把它比作執行緒池中最大的執行緒數。不過現在銀行的行長認為現在業務比較少,開10個視窗就夠了,也就是說當前只需要開啟10個視窗就足夠辦理業務了,不需要同時開啟20個那麼多去浪費資源。這個我們就可以把它比作是執行緒池中的核心執行緒數。在銀行辦理業務的時候工作人員不可能像機器一樣無休止的一直工作的吧!他有時候需要停下來休息一會兒,喝喝水或者上上廁所。這個我們就可以比作執行緒的保持活躍時間,也就是休息時間。很不巧的是今天你去銀行辦理取錢業務的時候發現人山人海啊!到處都是辦理業務的人。這時候銀行的行長髮話了,把之前沒有開啟的空閒視窗都開啟吧!這樣辦理業務會快一些,辦理業務的群眾才不會等那麼久。可是今天實在是太多人了,20個視窗同時開啟了都無法滿足現有的狀態啊!整個銀行都擠滿了人啊!這時候銀行的行長也沒辦法了,怎麼辦?這時候行長又發話了。這樣吧!我們先把銀行的門關閉一下,讓在裡面的正在排隊的人先辦理業務,接下來要來銀行辦理業務的人先在銀行的門外面等著吧!等到裡面的人辦理好業務,銀行有資源為外面等待的人辦理業務的時候再把銀行的門開啟,讓外面的人進來辦理業務吧!
整個執行緒池的工作機制就類似於上面的銀行辦理業務的例子,希望大家看完後對執行緒池有一個全新的認識。好了,下面就讓我們來寫對應的程式碼練練手吧!
#
詳細程式碼如下:
#
public class ThreadPoolConstructor {
private static ThreadPool mThreadPoolCenter;
//獲取執行緒池的物件
public static ThreadPool getThreadPool() {
if (mThreadPoolCenter == null) {
// 獲取CPU個數,獲取CPU個數的主要目的是為了根據不同的手機CPU的核數不同,從而設定執行緒的數目不同
int CPUNum = Runtime.getRuntime().availableProcessors();
//設定執行緒的最大執行緒數最好的方案就是根據CPU的核數乘以2再加上1.
int count = CPUNum * 2 + 1;
if (CPUNum < 8) {
count = 8;
}
mThreadPoolCenter = new ThreadPool(count, count, 0L);
}
return mThreadPoolCenter;
}
public static class ThreadPool {
private int coreThreadNumber;// 核心執行緒的數目
private int maxThreadNumber;// 最大執行緒的數目
private long keepThreadTime;// 保持執行緒的活躍時間(即為:休息時間)
private ThreadPoolExecutor executor;
private ThreadPool(int coreThreadNumber, int maxThreadNumber,
long keepThreadTime) {
this.coreThreadNumber = coreThreadNumber;
this.maxThreadNumber = maxThreadNumber;
this.keepThreadTime = keepThreadTime;
}
//執行對應執行緒任務
public void execute(Runnable r) {
if (executor == null) {
// 引數一:核心執行緒的數目
// 引數二:最大執行緒的數目
// 引數三:保持執行緒的活躍時間(即為:休息時間)
// 引數四:活躍時間的單位
// 引數五:執行緒佇列
// 引數六:執行緒工廠
// 引數七:異常處理策略
executor = new ThreadPoolExecutor(coreThreadNumber,
maxThreadNumber, keepThreadTime, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
}
executor.execute(r);// 將當前Runnable物件放線上程池中
}
// 移除對應的執行緒任務
public void cancel(Runnable r) {
if (executor != null) {
executor.getQueue().remove(r);
}
}
}
}
public class MainActivity extends AppCompatActivity {
private Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
useThreadPoolConstructorMethod();
}
//使用執行緒池的方法
private void useThreadPoolConstructorMethod() {
//只需要呼叫下面這一句你就可以使用自己構造出來的執行緒池了
ThreadPoolConstructor.getThreadPool().execute(new Runnable() {
@Override
public void run() {
SystemClock.sleep(3000);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, "成功呼叫", Toast.LENGTH_SHORT).show();
}
});
}
});
}
}