Android執行緒池學習
在學習執行緒池之前需要先了解幾個java的執行緒池
1.newCachedThreadPool
建立一個可快取執行緒池,根據長度靈活回收,若無空閒執行緒,則新建執行緒
2.newFixedThreadPool
建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
3.newScheduledThreadPool
建立一個定長執行緒池,支援定時及週期性任務執行。
4.newSingleThreadExecutor
建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
他們各自有各自的不足和優點,這裡我們且說他們自身的不足吧
第一種,沒有最大併發數的控制,所以在沒有空執行緒情況下會無限新建執行緒,
第二/三種,控制了最大併發數限制,但是沒有充分利用空閒執行緒.
第四種,每次只能執行一個單執行緒.
相對以上四種來說,我們自己寫的執行緒池管理充分對其缺點進行了彌補.
再來看看非同步任務類AsyncTask
原理
5個併發數執行緒,128個最大可執行執行緒,空閒時間為1秒
其也存在著很大隱患,比如:
併發數和最大執行緒池不可控
當執行緒池超過最大併發數後就會崩潰,因此沒有對做"等待"處理
容易造成記憶體洩漏
更多請參考:http://blog.csdn.net/boyupeng/article/details/49001215
說了這麼多別人的不足,是不是覺得自己寫的就很厲害了呢,不是,此次篇幅只是簡單根據以上各自的進行綜合而已,也有很多沒有進行詳細的處理.
先看看我將要實現的原理
①釋出一個任務,任務有三種狀態值,待執行,執行中,已完成
初始化為待執行
②根據執行緒佇列(池)中是否存在空閒執行緒來新建或者複用執行緒
③超過執行緒池最大執行緒數限制,則任務佇列處於wait狀態
④looper不斷檢測是否存在wait的任務進行迴圈執行
首先是任務抽象類
/** * 主題:任務抽象類 */ public abstract class ATask { public static final int TASK_WAITING = 1001;// 待執行 public static final int TASK_EXECUTING = 1002;// 執行中 public static final int TASK_COMPLETE = 1003;// 已完成 private int status = TASK_WAITING; private String[] params; // 後臺執行 public abstract Object doInBackground(String... params); // 回撥結果 public void doPost(Object object) { } /** * 執行任務 * * @param params */ public void execute(String... params) { this.params = params; execute(); } /** * 執行任務 */ public void execute() { XTaskQueue.getIntance().add(this); XLooper.getInstance().loop(); } /** * 更新任務狀態 * * @param status */ public void updateStatus(int status) { this.status = status; } /** * 獲取任務狀態 * * @return */ public int getStatus() { return status; } String[] getParams() { return params; } }
其次任務佇列
/**
* 主題:任務佇列
*/
public class XTaskQueue {
private ArrayList<ATask> taskQueue = new ArrayList();// 任務佇列
private ArrayList<ATask> waitingTasks = new ArrayList();// 待執行任務
private static XTaskQueue intance = new XTaskQueue();
private XTaskQueue() {
}
public static XTaskQueue getIntance() {
return intance;
}
/**
* 新增一個任務
*
* @param task
*/
public void add(ATask task) {
taskQueue.add(taskQueue.size(),task);
}
/**
* 獲取待執行任務
*
* @return
*/
public ArrayList<ATask> getWaitingTasks() {
waitingTasks.clear();
for (ATask task : taskQueue) {
if (task.getStatus() == ATask.TASK_WAITING) {
waitingTasks.add(task);
}
}
return waitingTasks;
}
public void clear(){
taskQueue.clear();
}
public int size(){
return taskQueue.size();
}
}
執行緒池
/**
* 主題:執行緒佇列
*/
public class XThreadQueue {
private int limit=3;
private ArrayList<XThread> threadQueue=new ArrayList<>();// 執行緒佇列
private ArrayList<XThread> idleThreads=new ArrayList<>();// 空閒執行緒
private static XThreadQueue instance=new XThreadQueue();
private XThreadQueue(){}
public static XThreadQueue getInstance(){
return instance;
}
public void add(XThread thread){
threadQueue.add(threadQueue.size(),thread);
}
public void clear(){
threadQueue.clear();
}
/**
* 最執行緒數
* @param count
*/
public void limit(int count){
this.limit=limit;
}
/**
* 獲取最大執行緒數
* @return
*/
public int getMaxLimitCount() {
return limit;
}
/**
* 獲取空閒執行緒
* @return
*/
public ArrayList<XThread> getIdleThreads(){
idleThreads.clear();
for(XThread thread:threadQueue){
if(thread.getStatus()==XThread.THREAD_IDLE){
idleThreads.add(thread);
}
}
return idleThreads;
}
/**
* 執行緒池數量
* @return
*/
public int size(){
return threadQueue.size();
}
}
looper
/**
* 主題:looper
*/
public class XLooper {
private boolean loop = false;
private static XLooper instance = new XLooper();
public static XLooper getInstance() {
return instance;
}
private XLooper() {
}
public synchronized void loop() {
loop = true;
ArrayList<ATask> waitingTasks = XTaskQueue.getIntance().getWaitingTasks();// 獲取待執行任務
ArrayList<XThread> idleThreads = XThreadQueue.getInstance().getIdleThreads();// 獲取空閒執行緒
if (waitingTasks.size() == 0) return;
Log.d("tag", "當前總任務數:" + XTaskQueue.getIntance().size() + ",當前匯流排程數:" + XThreadQueue.getInstance().size() + ",當前待執行任務數:" + waitingTasks.size() + ",當前空閒執行緒數:" + idleThreads.size());
if (idleThreads.size() > 0) {
int count = Math.min(waitingTasks.size(), idleThreads.size());
for (int i = 0; i < count; i++) {
Log.d("tag", "複用執行緒");
ATask task = waitingTasks.get(i);
XThread thread = idleThreads.get(i);
thread.insert(task, task.getParams());
}
} else {
if (XThreadQueue.getInstance().size() < XThreadQueue.getInstance().getMaxLimitCount()) {// 當前執行緒池還沒有達到限制數量,則還可以新建執行緒並執行任務
int remainCount = XThreadQueue.getInstance().getMaxLimitCount() - XThreadQueue.getInstance().size();// 剩餘可建立執行緒數
int canCreateCount = Math.min(remainCount, waitingTasks.size());// 取消可建立執行緒和待執行任務大小的最小值
for (int i = 0; i < canCreateCount; i++) {
Log.d("tag", "新建執行緒");
ATask task = waitingTasks.get(i);
XThread thread = new XThread();
thread.insert(task, task.getParams());
XThreadQueue.getInstance().add(thread);
thread.start();
}
}
}
}
public void cancel() {
loop = false;
XThreadQueue.getInstance().clear();
XTaskQueue.getIntance().clear();
}
public boolean isLoop(){
return loop;
}
}
工作執行緒
/**
* 主題:工作執行緒
*/
public class XThread extends Thread {
public static final int THREAD_EXETUING = 1004;// 執行中
public static final int THREAD_IDLE = 1005;// 空閒狀態
private int status = THREAD_IDLE;// 預設為空閒狀態
private ATask task;
private String[] params;
@Override
public void run() {
while (XLooper.getInstance().isLoop()) {
if(task!=null) {
Object object = task.doInBackground(params);
task.doPost(object);
status = THREAD_IDLE;
task.updateStatus(ATask.TASK_COMPLETE);
Log.d("tag", "一個任務已完成");
task = null;
XLooper.getInstance().loop();
}
}
}
/**
* 插入任務
*
* @param task
*/
public void insert(ATask task, String... params) {
this.task = task;
if (params != null) {
this.params = params;
}
status = THREAD_EXETUING;
task.updateStatus(ATask.TASK_EXECUTING);
}
/**
* 重新整理狀態
*/
public void updateStatus(int status) {
this.status = status;
}
/**
* 獲取執行緒狀態
*
* @return
*/
public int getStatus() {
return status;
}
}
用法:
新建任務
/**
* 主題:
*/
public class Task extends ATask {
@Override
public Object doInBackground(String... params) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
public void doPost(Object object) {
super.doPost(object);
}
}
其次使用即可
Task task=new Task();
task.execute();
本次例項編寫也有很多沒有完善的地方,比如空執行緒超時回收等.