異步任務AsyncTask 源碼 位址 http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/os/AsyncTask.java
最近在Android開發上遇到線程遇到諸多問題,特此記錄下。也希望能為諸君貢獻一二。
Code一版
直接使用new Thread
new Thread(new Runnable() {
@Override
public void run() {
doSomething();//執行代碼(耗時等 資料庫操作等)
}
}).start();
很明顯的弊端,Code中太多地方需要線程的地方,new 了無數個線程。
1.每次new Thread建立對象性能差
2. 線程缺乏統一管理,可能無限制建立線程,互相之間競争,即可能占用過多的系統資源導緻當機
3.缺乏更多功能,比如定時執行,定期執行,線程中斷。
總之最後很紮心,而且你能想象這放在一個性能很差的Android機裡面運作麼~~
Code二版
使用定義的線程池
先來個我定義的
/**
* 線程池管理(線程統一排程管理)
*/
public final class ThreadPoolManager {
public static class ThreadPoolProxy {
ThreadPoolExecutor mExecutor;
private int mCorePoolSize;
private int mMaximumPoolSize;
/**
* @param corePoolSize 核心池的大小
* @param maximumPoolSize 最大線程數
*/
public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) {
mCorePoolSize = corePoolSize;
mMaximumPoolSize = maximumPoolSize;
}
/**
* 初始化ThreadPoolExecutor
* 雙重檢查加鎖,隻有在第一次執行個體化的時候才啟用同步機制,提高了性能
*/
private void initThreadPoolExecutor() {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
synchronized (ThreadPoolProxy.class) {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
long keepAliveTime = 3000;
TimeUnit unit = TimeUnit.MILLISECONDS;
BlockingQueue workQueue = new LinkedBlockingDeque<>();
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
mExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, handler);
}
}
}
}
/**
執行任務和送出任務的差別?
1.有無傳回值
execute->沒有傳回值
submit-->有傳回值
2.Future的具體作用?
1.有方法可以接收一個任務執行完成之後的結果,其實就是get方法,get方法是一個阻塞方法
2.get方法的簽名抛出了異常===>可以處理任務執行過程中可能遇到的異常
*/
/**
* 執行任務
*/
public void execute(Runnable task) {
initThreadPoolExecutor();
mExecutor.execute(task);
}
/**
* 送出任務
*/
public Future submit(Runnable task) {
initThreadPoolExecutor();
return mExecutor.submit(task);
}
/**
* 移除任務
*/
public void remove(Runnable task) {
initThreadPoolExecutor();
mExecutor.remove(task);
}
}
/**
* 線程池工廠類
* Created by Samson on 2018/2/11.
* 使用方法
* ThreadPoolProxyFactory .getNormalThreadPoolProxy().execute(Runnable);
*/
public static class ThreadPoolProxyFactory {
private static ThreadPoolProxy mNormalThreadPoolProxy;
private static ThreadPoolProxy mDownLoadThreadPoolProxy;
/**
* 得到普通線程池代理對象mNormalThreadPoolProxy
*/
public static ThreadPoolProxy getNormalThreadPoolProxy() {
if (mNormalThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mNormalThreadPoolProxy == null) {
mNormalThreadPoolProxy = new ThreadPoolProxy(10 , 10);
}
}
}
return mNormalThreadPoolProxy;
}
/**
* 下載下傳專用
* 得到下載下傳線程池代理對象mDownLoadThreadPoolProxy
*/
public static ThreadPoolProxy getDownLoadThreadPoolProxy() {
if (mDownLoadThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mDownLoadThreadPoolProxy == null) {
mDownLoadThreadPoolProxy = new ThreadPoolProxy(3, 3);
}
}
}
return mDownLoadThreadPoolProxy;
}
}
}
如何使用:
ThreadPoolManager.ThreadPoolProxyFactory.getNormalThreadPoolProxy()
.execute(new Runnable() {
@Override
public void run() {
doSomething();
}
});
-----------------------------------------lambda
ThreadPoolManager.ThreadPoolProxyFactory.getNormalThreadPoolProxy()
.execute(() -> {doSomething();});
Code三版
手動控制版線程池(将所有事務分類放在規定的線程中執行,(未不同類别的事務規定不同的線程))
/**
* 本地資料處理和耗時處理用不同線程處理
*/
public class ThreadPoolUtil {
private List<Run> runList = new ArrayList<>();
private List<Run> runListTemp = new ArrayList<>();
private Thread thread = null;
public interface Run {
void run();
}
private ThreadPoolUtil() {
init();
}
private void init() {
if (thread == null) {
thread = new Thread(() -> {
for (; ; ) {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
dealRun();
}
});
thread.start();
}
}
private final Object lock = new Object();
private static ThreadPoolUtil _INSTANCESEND = null;
private static ThreadPoolUtil _INSTANCESERVER = null;
private static ThreadPoolUtil _INSTANCENORMAL = null;
/**
* 發消息
* @return
*/
public static ThreadPoolUtil getSendMsgInstance() {
if (_INSTANCESEND == null) {
_INSTANCESEND = new ThreadPoolUtil();
}
return _INSTANCESEND;
}
/**
* 收消息
* @return
*/
public static ThreadPoolUtil getGetMsgInstance() {
if (_INSTANCESERVER == null) {
_INSTANCESERVER = new ThreadPoolUtil();
}
return _INSTANCESERVER;
}
/**
* 普通通用消息
* @return
*/
public static ThreadPoolUtil getNormalInstance() {
if (_INSTANCENORMAL == null) {
_INSTANCENORMAL = new ThreadPoolUtil();
}
return _INSTANCENORMAL;
}
public void addRun(Run run) {
runListTemp.add(run);
synchronized (lock) {
runList.addAll(runListTemp);
runListTemp.clear();
lock.notify();
}
}
private Run getRun() {
if (runList.size() <= 0) {
return null;
}
Run run = null;
synchronized (lock) {
run = runList.get(0);
runList.remove(0);
}
return run;
}
private void dealRun() {
try {
for (Run run = getRun(); (run) != null; ) {
run.run();
run = getRun();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
如何使用:不同的分類可 get 不同的線程來處理。
ThreadPoolUtil.getNormalInstance().addRun(new ThreadPoolUtil.Run() {
@Override
public void run() {
doSomething();
}
});
-----------------------------------------lambda
ThreadPoolUtil.getNormalInstance().addRun(() ->{
doSomething();
});
2,3兩種方式 差別
2方式一旦有線程操作失誤可能會導緻全線線程癱瘓,導緻整個線程池無法正常的運作下去,
3方式使用失誤 基本隻會導緻其一線程癱瘓,更易于查找 修複。