赞
踩
public class FibonacciTask extends AsyncTask<Integer, Float, Integer> { private static final String TAG = "FibonacciTask"; @Override protected Integer doInBackground(Integer... integers) { int sum = 0, length = integers.length; for(int i = 0 ; i < length; i++) { sum += fn(integers[i]); publishProgress(((float)(i + 1) / (float)length) * 100); Log.d(TAG, "doInBackground " + printThread()); } return sum; } @Override protected void onPreExecute() { // super.onPreExecute(); 空方法 // 这里可以做一些初始化,打印一下调用就好 Log.d(TAG, "onPreExecute" + printThread()); printThread(); } @Override protected void onPostExecute(Integer integer) { // super.onPostExecute(integer); 空方法 // 打印一下结果 Log.d(TAG, "onPostExecute: " + integer + printThread()); } @Override protected void onProgressUpdate(Float... values) { // super.onProgressUpdate(values); 空方法 // 打印一下进度 Log.d(TAG, "onProgressUpdate: " + values[0] + printThread()); } @Override protected void onCancelled(Integer integer) { // 父类 调了onCancelled(),onCancelled()为空方法 // super.onCancelled(integer); // 打印一下调用 Log.d(TAG, "onCancelled("+ integer +")" + printThread()); } @Override protected void onCancelled() { // super.onCancelled(); 空方法 // 打印一下调用 Log.d(TAG, "onCancelled()" + printThread()); } private int fn(int n) { if(n == 1 || n == 2) { return 1; } return fn(n - 1) + fn(n - 2); } private String printThread() { return " threadId:" + Thread.currentThread().getId(); } }
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate: threadId:" + Thread.currentThread().getId()); // 创建一个异步任务对象 final FibonacciTask task = new FibonacciTask(); // 开始执行 task.execute(10, 11, 15, 30, 40); Button button = findViewById(R.id.cancel); // 点击取消任务 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 这个boolean参数表示是否中断正在执行的任务 task.cancel(true); } }); } }
2020-05-19 23:18:59.862 2876-2876/? D/MainActivity: onCreate: threadId:2
2020-05-19 23:18:59.862 2876-2876/? D/FibonacciTask: onPreExecute threadId:2
2020-05-19 23:19:01.416 2876-2903/comlscag.learn D/FibonacciTask: doInBackground threadId:200
2020-05-19 23:19:01.416 2876-2876/comlscag.learn D/FibonacciTask: onProgressUpdate: 20.0 threadId:2
2020-05-19 23:19:03.854 2876-2903/comlscag.learn D/FibonacciTask: doInBackground threadId:200
2020-05-19 23:19:03.854 2876-2876/comlscag.learn D/FibonacciTask: onProgressUpdate: 40.0 threadId:2
2020-05-19 23:19:07.748 2876-2903/comlscag.learn D/FibonacciTask: doInBackground threadId:200
2020-05-19 23:19:07.748 2876-2876/comlscag.learn D/FibonacciTask: onProgressUpdate: 60.000004 threadId:2
2020-05-19 23:19:14.033 2876-2903/comlscag.learn D/FibonacciTask: doInBackground threadId:200
2020-05-19 23:19:14.033 2876-2876/comlscag.learn D/FibonacciTask: onProgressUpdate: 80.0 threadId:2
2020-05-19 23:19:24.213 2876-2903/comlscag.learn D/FibonacciTask: doInBackground threadId:200
2020-05-19 23:19:24.213 2876-2876/comlscag.learn D/FibonacciTask: onProgressUpdate: 100.0 threadId:2
2020-05-19 23:19:24.213 2876-2876/comlscag.learn D/FibonacciTask: onPostExecute: 1670731762 threadId:2
可以看到除了doInBackground以外的方法都是在主线程执行的。
public AsyncTask() { // 调用AsyncTask(@Nullable Looper callbackLooper),传入Looper为空 this((Looper) null); } public AsyncTask(@Nullable Handler handler) { this(handler != null ? handler.getLooper() : null); } /** * Creates a new asynchronous task. This constructor must be invoked on the UI thread. * 必须在主线程调用?为什么? * @hide */ public AsyncTask(@Nullable Looper callbackLooper) { // 默认的构造方法looper传进来是null,这里会调getMainHandler() 获取handler, // 如果反射传进来了指定的looper,并且不是主线程的looper,则会将handler指向对应线程(原理和HandlerThread一样) mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); // 创建一个WorkerRunnable对象,它是任务的实际执行者,详见2.2.4 mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Result result = null; try { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked result = doInBackground(mParams); Binder.flushPendingCommands(); } catch (Throwable tr) { mCancelled.set(true); throw tr; } finally { postResult(result); } return result; } }; // 创建一个FutureTask对象,传入刚才创建的worker, // 可以看到这里重写了done方法,FutureTask的介绍详见2.2.5 mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } catch (InterruptedException e) { android.util.Log.w(LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException("An error occurred while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
可以看到,每个异步任务对象都会实例化一个mWorker对象和一个mFuture对象,mWorker是任务的实际执行者,mFuture提供了对任务管理(触发、调度、取消、传递结果)等功能。
public final AsyncTask<Params, Progress, Result> execute(Params... params) { // sDefaultExecutor详见2.2.2 return executeOnExecutor(sDefaultExecutor, params); } public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { // 执行过execute的异步任务对象无法再执行第二次 if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } } // 修改异步任务状态 mStatus = Status.RUNNING; // 第一个回调 onPreExecute(); // 给worker设置参数 mWorker.mParams = params; // 串行执行器执行任务 exec.execute(mFuture); return this; }
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; private static class SerialExecutor implements Executor { // 维护了一个任务队列 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; // 执行方法,将任务入队,如果当前没有执行任务,就开始调用线程池执行,否则等当前任务执行完成才执行下一个任务,典型的串行控制器,多个异步任务执行execute时是串行执行的 public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { // 调用线程池执行任务 THREAD_POOL_EXECUTOR.execute(mActive); } } }
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // 核心线程数:可用cpu核心数 <= 3为2个;可用cpu核心数 >= 4为4个 private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4)); // 线程池最大容量:cpu核心数*2 +1 private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; // 非核心线程最大存活时间:30秒 private static final int KEEP_ALIVE_SECONDS = 30; // 线程工厂:给每个线程按顺序指定了name private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); } }; // 任务队列 private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); public static final Executor THREAD_POOL_EXECUTOR; static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); THREAD_POOL_EXECUTOR = threadPoolExecutor; }
可以看到线程池是支持多个任务并行执行的,但由于串行控制器的存在,实际上多个异步任务是串行执行的,当然,可以通过反射hook掉串行执行器,实现并行的异步任务。
串行控制器会依次将任务队列中的任务交给线程池执行,执行的任务正是创建AsyncTask实例时构造的mFuture对象,mFuture对象又持有了WorkRunnable对象mWorker,接下来看看这两个对象是如何工作的。
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
public interface Callable<V> {
V call() throws Exception;
}
WorkerRunnable是AsyncTask的静态内部类,实现了Callable接口
根据1.1中创建的匿名类可以看到WorkerRunnable会持有doInBackground的参数mParams,
并且返回处理结果result
FutureTask间接实现了Runnable接口,在被线程池调度时会执行run方法。
// 异步任务中创建mFuture的构造方法 public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } // FutureTask中done是个空方法 protected void done() { } public void run() { if (state != NEW || !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } } protected void set(V v) { if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) { outcome = v; U.putOrderedInt(this, STATE, NORMAL); // final state finishCompletion(); } }
其run方法判断了任务状态,如果不是新任务不会被执行,同时用CAS的方法记录了当前执行任务线程到FutureTask的runner字段,接着调用了mWorker的run方法真正执行任务,如果任务被成功执行,则会调set方法修改当前任务状态,并调finishCompletion结束任务。
最后看一下AsyncTask的取消过程
// AsyncTask.cancel public final boolean cancel(boolean mayInterruptIfRunning) { // 设置取消状态,并执行mFuture的cancel方法 mCancelled.set(true); return mFuture.cancel(mayInterruptIfRunning); } // FutureTask.cancel public boolean cancel(boolean mayInterruptIfRunning) { // 判断并修改任务状态,如果设置cancel是允许中断当前执行任务的,则会中断正在执行的线程 if (!(state == NEW && U.compareAndSwapInt(this, STATE, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) return false; try { // in case call to interrupt throws exception if (mayInterruptIfRunning) { try { Thread t = runner; if (t != null) t.interrupt(); } finally { // final state U.putOrderedInt(this, STATE, INTERRUPTED); } } } finally { // 最终调用finishCompletion结束任务 finishCompletion(); } return true; } private void finishCompletion() { // assert state > COMPLETING; for (WaitNode q; (q = waiters) != null;) { if (U.compareAndSwapObject(this, WAITERS, q, null)) { for (;;) { Thread t = q.thread; if (t != null) { q.thread = null; LockSupport.unpark(t); } WaitNode next = q.next; if (next == null) break; q.next = null; // unlink to help gc q = next; } break; } } // 可以看到这里调了done方法,可以回到2.1.1的构造方法中看到,done方法会将已经执行的结果传递出去 done(); callable = null; // to reduce footprint }
AsyncTask的任务取消操作是基于FutureTask的取消操作执行的,提供了中断当前任务\不中断当前任务,两种取消方法,并且会在取消时返回已执行结果。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。