AsyncTask能够适当地、简单地用于 UI线程。 这个类不需要操作线程(handlers)就可以完成后台操作将结果返回UI。
AsyncTask设计目的在于在framework层完成 Thread and Handler交互。Asyn应该被用在短操作上(数秒内完成)。如果需要保持线程运行长时间,相当推荐使用APIs提供的java.util.concurrent例如:Executor
, ThreadPoolExecutor
and FutureTask
.
异步任务的定义是一个在后台线程上运行,其结果是在 UI线程上发布的计算。 异步任务被定义成三种泛型类型: Params,Progress和 Result;和四个步骤:
onPreExecute
doInBackground,
onProgressUpdate
onPostExecute
AsyncTask是基于FutureTask封装的异步操作类支持 |
(1)多线程串行模式执行:private ExecutorService SINGLE_TASK = Executors.newSingleThreadExecutor();
(2)多线程限制模式执行:private ExecutorService LIMITED_TASK = Executors.newFixedThreadPool(3);
(3)多线程并行模式执行:private ExecutorService FULL_TASK = Executors.newCachedThreadPool ();
(4)提供查询线程是否取消:isCancelled()
(5)支持线程取消:onCancelled(Result result)
(6)提供获取线程状态:getStatus()
AsyncTask在线程执行层面提供了三种方法 |
(1)#execute()提交任务,按照先后顺序每次只运行一个。
也就是说它是按照提交的次序,每次只启动一个线程执行一个任务,完成之后在执行第二个任务,也就是相当于只有一个后台线程在执行所提交的任务类似于:Executors.newSingleThreadExecutor();
(2)#execute(Runnable runnable)提交任务,按照先后顺序每次只运行一个。参考(1)
(3)#executeOnExecutor(Executor exec, Params... params)
这个接口允许开发者提供自定义的线程池来运行和调度Thread。如果你想让所有的任务都能同时并发运行,那就创建一个没有限制的线程池,参考上述:FULL_TASK,并提供给AsyncTask,这样这个AsyncTask实例就有了自己的线程池而不必使用AsyncTask默认的。同理可以使用LIMITED_TASK。
AsyncTask代码示例 |
代码将线程执行过程转化为可视化效果:
/** * 线程池二:使用AsyncTask实现线程池控制 * * */ private void initViewAsync() { setContentView(R.layout. activity_thread_pool); mBar1 = (SeekBar) findViewById(R.id. seekBar1); mBar2 = (SeekBar) findViewById(R.id. seekBar2); mBar3 = (SeekBar) findViewById(R.id. seekBar3); mBar4 = (SeekBar) findViewById(R.id. seekBar4); mBar5 = (SeekBar) findViewById(R.id. seekBar5); mBar6 = (SeekBar) findViewById(R.id. seekBar6); mBar1.setMax(100); mBar2.setMax(100); mBar3.setMax(100); mBar4.setMax(100); mBar5.setMax(100); mBar6.setMax(100); MyAsynctask asyncTask1 = new MyAsynctask("bar1" ); MyAsynctask asyncTask2 = new MyAsynctask("bar2" ); MyAsynctask asyncTask3 = new MyAsynctask("bar3" ); MyAsynctask asyncTask4 = new MyAsynctask("bar4" ); MyAsynctask asyncTask5 = new MyAsynctask("bar5" ); MyAsynctask asyncTask6 = new MyAsynctask("bar6" ); asyncTask1.executeOnExecutor( FULL_TASK); asyncTask2.executeOnExecutor( FULL_TASK); asyncTask3.executeOnExecutor( FULL_TASK); asyncTask4.executeOnExecutor( FULL_TASK); asyncTask5.executeOnExecutor( FULL_TASK); asyncTask6.executeOnExecutor( FULL_TASK); } class MyAsynctask extends AsyncTask<Void, Integer, Void> { private String mKey = null; public MyAsynctask(String key) { mKey = key; } @Override protected Void doInBackground(Void... params) { if ("bar1" .equals(mKey )) { while (mBar1 .getProgress() < 100) { int i = mBar1 .getProgress() + 1; if (0 == i % 10) { Log. i(TAG, "mBar1 number:" + i ); } try { Thread. sleep(mTime); } catch (InterruptedException e ) { e.printStackTrace(); } publishProgress( i); } } else if ("bar2" .equals(mKey )) { while (mBar2 .getProgress() < 100) { int i = mBar2 .getProgress() + 1; if (0 == i % 10) { Log. i(TAG, "mBar2 number:" + i ); } try { Thread. sleep(mTime); } catch (InterruptedException e ) { e.printStackTrace(); } publishProgress( i); } } else if ("bar3" .equals(mKey )) { while (mBar3 .getProgress() < 100) { int i = mBar3 .getProgress() + 1; if (0 == i % 10) { Log. i(TAG, "mBar3 number:" + i ); } try { Thread. sleep(mTime); } catch (InterruptedException e ) { e.printStackTrace(); } publishProgress( i); } } else if ("bar4" .equals(mKey )) { while (mBar4 .getProgress() < 100) { int i = mBar4 .getProgress() + 1; if (0 == i % 10) { Log. i(TAG, "mBar4 number:" + i ); } try { Thread. sleep(mTime); } catch (InterruptedException e ) { e.printStackTrace(); } publishProgress( i); } } else if ("bar5" .equals(mKey )) { while (mBar5 .getProgress() < 100) { int i = mBar5 .getProgress() + 1; if (0 == i % 10) { Log. i(TAG, "mBar5 number:" + i ); } try { Thread. sleep(mTime); } catch (InterruptedException e ) { e.printStackTrace(); } publishProgress( i); } } else if ("bar6" .equals(mKey )) { while (mBar6 .getProgress() < 100) { int i = mBar6 .getProgress() + 1; if (0 == i % 10) { Log. i(TAG, "mBar6 number:" + i ); } try { Thread. sleep(mTime); } catch (InterruptedException e ) { e.printStackTrace(); } publishProgress( i); } } return null ; } @Override protected void onPostExecute(Void result ) { Log. i(TAG, "onPostExecute"); } @Override protected void onPreExecute() { Log. i(TAG, "onPreExecute"); } @Override protected void onProgressUpdate(Integer... values ) { if ("bar1" .equals(mKey )) { mBar1.setProgress( values[0]); } else if ("bar2" .equals(mKey )) { mBar2.setProgress( mBar2.getProgress() + 1); } else if ("bar3" .equals(mKey )) { mBar3.setProgress( mBar3.getProgress() + 1); } else if ("bar4" .equals(mKey )) { mBar4.setProgress( mBar4.getProgress() + 1); } else if ("bar5" .equals(mKey )) { mBar5.setProgress( mBar5.getProgress() + 1); } else if ("bar6" .equals(mKey )) { mBar6.setProgress( mBar6.getProgress() + 1); } } }
布局文件代码activity_thread_pool.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Task#1" android:textAppearance="?android:attr/textAppearanceLarge" /> <SeekBar android:id="@+id/seekBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1px" android:background="#dddddd"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Task#2" android:textAppearance="?android:attr/textAppearanceLarge" /> <SeekBar android:id="@+id/seekBar2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1px" android:background="#dddddd"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Task#3" android:textAppearance="?android:attr/textAppearanceLarge" /> <SeekBar android:id="@+id/seekBar3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1px" android:background="#dddddd"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Task#4" android:textAppearance="?android:attr/textAppearanceLarge" /> <SeekBar android:id="@+id/seekBar4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1px" android:background="#dddddd"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Task#5" android:textAppearance="?android:attr/textAppearanceLarge" /> <SeekBar android:id="@+id/seekBar5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1px" android:background="#dddddd"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Task#6" android:textAppearance="?android:attr/textAppearanceLarge" /> <SeekBar android:id="@+id/seekBar6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1px" android:background="#dddddd"/> </LinearLayout>
执行效果:
private static final int CPU_COUNT = Runtime. getRuntime().availableProcessors(); private static final int CORE_POOL_SIZE = CPU_COUNT + 1; private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE = 1; 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); /** * An {@link Executor} that can be used to execute tasks in parallel. */ public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit. SECONDS, sPoolWorkQueue , sThreadFactory); /** * An {@link Executor} that executes tasks one at a time in serial * order. This serialization is global to a particular process. */ public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; private static InternalHandler sHandler; private final WorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture; private volatile Status mStatus = Status.PENDING; private final AtomicBoolean mCancelled = new AtomicBoolean(); private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
声明中可以看出,变量THREAD_POOL_EXECUTOR 和sHandler 都为静态变量static,为进程范围内共享的,属于类的作用范围是CLASSPATH,其中一个进程就是一个VM。
声明中可以看出,变量sDefaultExecutor 和mStatus 使用volatile关键字声明,volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.
声明中可以看出,变量mCancelled 和mTaskInvoked 类型为AtomicBoolean ,表示可以用原子方式更新的 boolean 值。有关原子变量属性的描述,请参阅 java.util.concurrent.atomic 包规范。AtomicBoolean 可用在应用程序中(如以原子方式更新的标志),但不能用于替换 Boolean。
构造函数分析
/** * Creates a new asynchronous task. This constructor must be invoked on the UI thread. */ public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true ); Process.setThreadPriority(Process. THREAD_PRIORITY_BACKGROUND); //noinspection unchecked Result result = doInBackground( mParams); Binder. flushPendingCommands(); return postResult(result ); } }; 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); } } }; }
其中WorkRunnable实现Callable<Result>,可参考上篇博客:线程池二:Java并发编程:Callable、Future和FutureTask中的:使用Callable+FutureTask获取执行结果,call()函数为线程执行函数,将doInBackground()函数放入其中,执行后台函数。
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }
执行函数分析
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { //判断当前线程是否为准备状态 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; // 线程前执行,UI线程 onPreExecute(); mWorker.mParams = params; // 执行mFuture exec.execute(mFuture); return this; } ... // 传递线程执行进度 protected final void publishProgress(Progress... values) { if (!isCancelled()) { sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } } // 结束线程 private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { // 线程结束调用 onPostExecute(result); } mStatus = Status.FINISHED; } // handler处理操作 private static class InternalHandler extends Handler { @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult result = (AsyncTaskResult) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } }
上面代码中可见executeOnExecutor需要在主线程中执行,依次调用:
(1)UI线程调用onPreExecute()
(2)线程中调用doInBackground( mParams)
(3)UI线程调用onProgressUpdate
(4)UI线程调用onPostExecute(result)
线程池二:Java并发编程:Callable、Future和FutureTaskAsyncTask|Android Developer
https://developer.xamarin.com/api/member/Android.OS.Binder.FlushPendingCommands()/