
除了Thread,AndroID中扮演线程的角色还有:AsyncTask、HandlerThread、IntentService。
AsyncTask:内部封装线程池、handler,便于在子线程中更新UI。HandlerThread:可以使用消息循环的线程,在它内部可以使用Handler。IntentService:内部使用HandlerThread执行任务,完毕后会自动退出。(相比后台线程)因是组件,优先级高,不易被杀死。
一、AndroID中的线程形态1.1 AsyncTask线程是 *** 作系统调度的最小单元,是一种受限的资源,不可能无限制的产生。且线程的创建和销毁需要相应的开销。且存在大量线程时,系统会通过时间片轮转的方式调度线程,因此线程不可能做到并行,除非线程数小于等于cpu数。所以需要 线程池,它可以缓存一定数量的线程,避免频繁地线程创建和销毁带来的系统开销。
AsyncTask是用来在线程池中处理异步任务,并可以把处理进度和结果发送到UI线程。
1.1.1 使用方法AsyncTask的基本使用方法,示例如下:
private voID testAsyncTask() { //一般要在主线程实例化。(实际在9.0上 子线程创建实例然后主线程execute没问题) //三个泛型参数依次表示参数类型、进度类型、结果类型。 //覆写的这几个方法不可以直接调用 AsyncTask<Integer, Integer, String> task = new AsyncTask<Integer, Integer, String>() { @OverrIDe protected voID onPreExecute() { super.onPreExecute(); //主线程执行,在异步任务之前 Log.i(TAG, "testAsyncTask onPreExecute: "); } @OverrIDe protected String doInBackground(Integer... integers) { Log.i(TAG, "testAsyncTask doInBackground: "); //任务在 线程池中执行 耗时 *** 作 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printstacktrace(); } //发出进度 publishProgress(50); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printstacktrace(); } //再发出进度 publishProgress(100); return "我是结果。参数是" + integers[0]; } @OverrIDe protected voID onPostExecute(String s) { super.onPostExecute(s); //在主线程执行,在异步任务执行完之后 Log.i(TAG, "testAsyncTask onPostExecute: "+s); } @OverrIDe protected voID onProgressUpdate(Integer... values) { super.onProgressUpdate(values); //执行在主线程,调用publishProgress()后就会执行 Log.i(TAG, "testAsyncTask onProgressUpdate: 进度:"+values[0]+"%"); } @OverrIDe protected voID onCancelled() { super.onCancelled(); //取消任务 } }; //必须要在主线程执行execute,且只能执行一次 task.execute(100); }执行结果日志如下:
2020-01-14 11:29:03.510 13209-13209/com.hfy.demo01 I/hfy: testAsyncTask onPreExecute: 2020-01-14 11:29:03.511 13209-13282/com.hfy.demo01 I/hfy: testAsyncTask doInBackground: 2020-01-14 11:29:04.558 13209-13209/com.hfy.demo01 I/hfy: testAsyncTask onProgressUpdate: 进度:50%2020-01-14 11:29:05.589 13209-13209/com.hfy.demo01 I/hfy: testAsyncTask onProgressUpdate: 进度:100%2020-01-14 11:29:05.590 13209-13209/com.hfy.demo01 I/hfy: testAsyncTask onPostExecute: 我是结果。参数是1001.1.2 原理分析:先看构造方法
public AsyncTask() { 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. */ public AsyncTask(@Nullable Looper callbackLooper) { mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); 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; } }; 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); } } }; } private static Handler getMainHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { //这里传入的是主线程的looper,所以用来把消息切到主线程 sHandler = new InternalHandler(Looper.getMainLooper()); } return sHandler; } }看到,首先使用主线程的Looper创建了InternalHandler实例。然后创建了WorkerRunnable的实例mWorker,call方法中看到调用了 doInBackground(mParams),可以猜想call方法是执行在线程池的。然后创建了FutureTask的实例mFuture并传入了mWorker,mFuture怎么使用的呢?后面会分析道。我们可以先看下Handler的实现InternalHandler:
private static class InternalHandler extends Handler { public InternalHandler(Looper looper) { super(looper); } @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; } } }看到有处理发送结果、处理发送进度的消息。消息从哪发来的呢?先留个疑问。继续看AsyncTask的execute方法:
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; /** * 串行 执行器 */ public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); @MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } @MainThread 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; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }execute方法走到了executeOnExecutor方法,先进行当前任务状态的判断,默认是准备执行任务的PENDING状态,然后变为RUNNING。但如果正在执行的RUNNING、执行完的FINISHED都会抛出异常。这也是一个任务实例只能执行一次的原因。然后又走到了onPreExecute(),因为execute执行在UI线程 所以也解释了其是执行在UI线程的原因。接着把参数赋值给mWorker,mFuture作为参数执行 静态的sDefaultExecutor的execute()方法。注意到sDefaultExecutor是SerialExecutor实例,去瞅瞅:
//线程池 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; } private static class SerialExecutor implements Executor { final arraydeque<Runnable> mTasks = new arraydeque<Runnable>(); Runnable mActive; //execute方法加了锁 public synchronized voID execute(final Runnable r) { //把r存入到任务队列的队尾 mTasks.offer(new Runnable() { public voID run() { try { r.run(); } finally { //任务执行完,就执行下一个 scheduleNext(); } } }); //把r存入任务队列后,然后当前没有取出的任务,就 取 队列头部 的任务执行 if (mActive == null) { scheduleNext(); } } protected synchronized voID scheduleNext() { //取 队列头部 的任务执行 if ((mActive = mTasks.poll()) != null) { //THREAD_POol_EXECUTOR是线程池 THREAD_POol_EXECUTOR.execute(mActive); } } }上面都有注释,可见SerialExecutor就是串行执行器,最终执行在THREAD_POol_EXECUTOR的线程池中。r.run()实际走的是FutureTask的run方法:
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } 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 { //callable的call方法 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); } }FutureTask的run方法中调用的传入的callable的call()方法,再结合上面AsyncTask的构造方法,mWorker就是实现callable的call()方法。所以里面的doInBackground方法就会串行的执行在线程池中。因为串行,那使用execute方法不能执行特别耗时的任务,否则会阻塞后面等待的任务。若想要并行,可采用AsyncTask的executeOnExecutor方法,传入线程池THREAD_POol_EXECUTOR即可。
还注意到,doInBackground执行完后调用了postResult(result),result就是doInBackground返回值:
private Handler getHandler() { return mHandler; } private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESulT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }看到,使用handler发送消息,消息类型就是MESSAGE_POST_RESulT,前面看到InternalHandler内部handleMessage是有处理的,就是调用task的finish方法:
private voID finish(Result result) { if (isCancelled()) { //如果任务取消了,回调onCancelled onCancelled(result); } else { //没有取消 onPostExecute(result); } //修改任务状态为完成 mStatus = Status.FINISHED; }可见如果没有调用cancel(),就会走onPostExecute,所以onPostExecute也是执行在UI线程的。
最后看下publishProgress方法:
protected final voID publishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } }如果没有取消任务,也是用handler,消息类型就是MESSAGE_POST_PROGRESS,前面看到InternalHandler内部handleMessage是有处理的,最后在UI线程执行onProgressUpdate方法。
举两个例子 总结
以上是内存溢出为你收集整理的Android的线程和线程池--《Android开发艺术探索》阅读笔记——第十一章全部内容,希望文章能够帮你解决Android的线程和线程池--《Android开发艺术探索》阅读笔记——第十一章所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)