Android 日常使用中经常会用到异步任务执行,以及有时需要在 UIThread 执行一些 UI 操作。执行异步任务也可以使用 Android 自带的 AsyncTask,但避免与其他应用或其他业务竞争资源,最好可以自己维护一个异步任务管理器。执行一些 UI 操作如果是在 Activity 或 Fragment 中倒是方便,但有时如果不在且需要 Toast 一些提示就不方便,因此封装了一个自定义的 TaskExcutor,提供以下方法:
/**
* 在【默认线程池】【串行执行】异步任务
* @param runnable 要执行的任务
*/
public static void executeInSerial(Runnable runnable);
/**
* 在【默认线程池】【并行执行】异步任务
* @param runnable 要执行的任务
*/
public static void executeInParallel(Runnable runnable);
/**
* 在 UI 线程执行任务
* @param runnable 要执行的任务
*/
public static void executeOnUiThread(Runnable runnable);
调用如下:
// 串行执行异步任务
TaskExecutor.executeInSerial(new Runnable() {
@Override
public void run() {
// do your work
}
});
// 并行执行异步任务
TaskExecutor.executeInParallel(new Runnable() {
@Override
public void run() {
// do your work
}
});
TaskExecutor.executeOnUiThread(new Runnable() {
@Override
public void run() {
// do ui operation
}
});
封装如下:
import android.os.Handler;
import android.os.Looper;
import java.util.ArrayDeque;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Author: AlanWang4523.
* Date: 2020-08-19 16:19.
* Mail: alanwang4523@gmail.com
*/
public class TaskExecutor {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
static final class TaskThreadFactory implements ThreadFactory {
private final AtomicInteger mCount = new AtomicInteger(1);
private final String tag;
TaskThreadFactory(String tag) {
this.tag = tag;
}
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "TaskExecutor-" + this.tag + mCount.getAndIncrement());
}
}
/**
* UI 线程执行器
*/
static final class UIThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
public final void execute(Runnable runnable) {
this.mHandler.post(runnable);
}
}
/**
* 默认的线程池执行器
*/
private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR;
/**
* UI 线程执行器
*/
private static final UIThreadExecutor UI_THREAD_EXECUTOR;
/**
* 默认的串行执行器
*/
private static final Executor SERIAL_EXECUTOR = new SerialExecutor();
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(128), new TaskThreadFactory("Default #"));
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
UI_THREAD_EXECUTOR = new UIThreadExecutor();
}
/**
* 在指定线程池执行的串行任务执行器
*/
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTaskDeque = new ArrayDeque<>();
Runnable mActiveTask;
public synchronized void execute(final Runnable r) {
mTaskDeque.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActiveTask == null) {
scheduleNext();
}
}
synchronized void scheduleNext() {
if ((mActiveTask = mTaskDeque.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActiveTask);
}
}
}
/**
* 在【默认线程池】【串行执行】异步任务
* @param runnable 要执行的任务
*/
public static void executeInSerial(Runnable runnable) {
SERIAL_EXECUTOR.execute(runnable);
}
/**
* 在【默认线程池】【并行执行】异步任务
* @param runnable 要执行的任务
*/
public static void executeInParallel(Runnable runnable) {
THREAD_POOL_EXECUTOR.execute(runnable);
}
/**
* 在 UI 线程执行任务
* @param runnable 要执行的任务
*/
public static void executeOnUiThread(Runnable runnable) {
UI_THREAD_EXECUTOR.execute(runnable);
}
}