在进行耗时操作时,一般new Thread().start();开启一个子线程,然后通过handler消息去更新ui(关于handler可以看这里:android Handler、Looper、Messsage、MessageQueue源码解析)或者利用AsyncTask进行耗时操作;

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//执行异步任务new WorkAsyncTask().execute();}class WorkAsyncTask extends AsyncTask<Void,Void,Void>{@Overrideprotected void onPreExecute() {super.onPreExecute();//任务开始的时候会回调   ui线程}@Overrideprotected Void doInBackground(Void... params) {//操作任务逻辑   子线程return null;}@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);//更新进度的时候会回调  ui线程}@Overrideprotected void onPostExecute(Void aVoid) {super.onPostExecute(aVoid);//操作完成更新ui回调 ui线程}}
}

这是一段简易的AsyncTask使用的代码,通过几个方法的重写和回调就完成了异步任务,表面上并没有看到线程之间的切换,其实AsyncTask源码中利用handler消息已经实现了线程之间的自由切换;先来看下AsyncTask的构造方法;

/*** Creates a new asynchronous task. This constructor must be invoked on the UI thread.*创建一个新的异步任务,这个构造方法的实例化必须在ui线程中*/public AsyncTask() {//实例化一个WorkerRunnable WorkerRunnable是一个抽闲类,implements Callable接口,所以在实例化的时候就必须重写其中的call()方法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//调用doInBackground方法,进行异步任务的操作,重写其方法,进行具体逻辑,并返回结果result = doInBackground(mParams);Binder.flushPendingCommands();} catch (Throwable tr) {mCancelled.set(true);throw tr;} finally {//调用postResult方法,该方法中会利用handler消息进行线程切换postResult(result);}//将异步任务的结果返回return result;}};//实例化一个FutureTask对象并将上面实例化好的WorkerRunnable作为参数传入//FutureTask<V> implements RunnableFuture<V>接口,可以重写其中的run方法mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {//会调用postResult方法,该方法中会利用handler消息进行线程切换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);}}};}

上面就是AsyncTask的构造方法,在使用AsyncTask的时候实例化一个AsyncTask对象后调用execute();方法就会去执行该异步任务;

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {//根据指定的参数去执行一个异步任务,并返回它自己,以保持对它的引用    //同时execute方法的执行要在ui线程中调用return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {if (mStatus != Status.PENDING) {switch (mStatus) {case RUNNING://不能执行异步任务,当前异步任务已经在runningthrow 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)");}}//执行了executeOnExecutor方法后就会将mStatus表示改为Status.RUNNING状态mStatus = Status.RUNNING;//会调用onPreExecute();方法,开始执行异步任务的时候可以重写做一些开始动作;//onPreExecute方法是在ui线程中调用onPreExecute();mWorker.mParams = params;//调用Executor中的execute去执行,并传入一个FutureTask实例exec.execute(mFuture);return this;
}

通过上面这段代码可以知道:

不能对同一个异步任务重复执行,一个异步任务只能被执行一次;

onPreExecute方法是在ui线程中调用;

在调用executeOnExecutor()方法时需要传入一个Executor对象,在实例化AsyncTask时就已经实例好一个全局的Executor了;

/*** 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 volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static class SerialExecutor implements Executor {//用于存储Runnable的容器final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();Runnable mActive;public synchronized void execute(final Runnable r) {//在Runnable容器的末尾插入一个RunnablemTasks.offer(new Runnable() {public void run() {try {//调用run方法r.run();} finally {scheduleNext();}}});if (mActive == null) {scheduleNext();}}protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {//调用Executor中的execute方法THREAD_POOL_EXECUTOR.execute(mActive);}}}

Executor中execute方法的调用已经是在子线程中调用了;

/*** An {@link Executor} that can be used to execute tasks in parallel.*/public static final Executor THREAD_POOL_EXECUTOR;static {//实例化一个线程池//CORE_POOL_SIZE 池中保持线程的数量//MAXIMUM_POOL_SIZE 池中允许的最大线程数//KEEP_ALIVE_SECONDS 闲置回收时间,当线程数大于内核时,这是多余空闲线程在终止之前等待新任务的最大时间。//TimeUnit.SECONDS 时间单位//sPoolWorkQueue 异步任务队列//sThreadFactory 线程工厂ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,sPoolWorkQueue, sThreadFactory);//设置允许超时threadPoolExecutor.allowCoreThreadTimeOut(true);THREAD_POOL_EXECUTOR = threadPoolExecutor;}

这是一段实例化线程池的静态代码块,下面是AsyncTask系统设置线程池的一些参数;

//获取cup数
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
//池中保持线程的数量
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//池中允许的最大线程数 cup数*2+1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 闲置回收时间
private static final int KEEP_ALIVE_SECONDS = 30;
//异步任务队列 128
private static final BlockingQueue<Runnable> sPoolWorkQueue =new LinkedBlockingQueue<Runnable>(128);
//线程工厂
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());}
};
如果当前线程池中的数量小于corePoolSize,创建并添加的任务。
如果当前线程池中的数量等于corePoolSize,缓冲队列 workQueue未满,那么任务被放入缓冲队列、等待任务调度执行。
如果当前线程池中的数量大于corePoolSize,缓冲队列workQueue已满,并且线程池中的数量小于maximumPoolSize,新提交任务会创建新线程执行任务。
如果当前线程池中的数量大于corePoolSize,缓冲队列workQueue已满,并且线程池中的数量等于maximumPoolSize,新提交任务由Handler处理。
当线程池中的线程大于corePoolSize时,多余线程空闲时间超过keepAliveTime时,会关闭这部分线程。    

执行完execute()方法,完成了线程的切换,这个时候在AsyncTask构造方法中实例化WorkerRunnable后会回调其中的call()方法,在call方法中就会去调用doInBackground(mParams);方法,所以doInBackground(mParams);方法的执行是在线性程中执行,具体逻辑由子类去实现,将执行结果返回后就会去调用postResult(result);方法;

private Result postResult(Result result) {@SuppressWarnings("unchecked")//通过getHandler获取Handler实例,然后再获取Message实例Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));//其实就是target.sendMessage(this); 也就是handler.sendMessage(message);message.sendToTarget();return result;
}
private static Handler getHandler() {synchronized (AsyncTask.class) {if (sHandler == null) {sHandler = new InternalHandler();}return sHandler;}
}

这个时候获得到doInBackground(mParams);中执行的结果,通过handler实现了线程的切换,并将结果进行了发送,通知ui去更新;

private static class InternalHandler extends Handler {public InternalHandler() {//在实例化handler时就已经实例化了一个mainLoopersuper(Looper.getMainLooper());}@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one result//在ui线程中处理异步任务的结果,更新uiresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS://在ui线程中更新异步任务的进度result.mTask.onProgressUpdate(result.mData);break;}}}
private void finish(Result result) {if (isCancelled()) {//如果异步任务已经取消就会调用onCancelled()方法onCancelled(result);} else {//调用onPostExecute方法更新ui,具体逻辑由子类实现onPostExecute(result);}//修改异步任务执行的状态mStatus = Status.FINISHED;
}

这样一个异步任务就执行完毕了,从中看出:

doInBackground(mParams);方法是在子线程中执行;

onPreExecute()、onProgressUpdate()、onPostExecute()、onCancelled()等方法都是在ui线程中执行;

onPreExecute()、onProgressUpdate()、onPostExecute()、onCancelled()等方法在ui线程中执行的原因是在实例化handler时实例化了一个main looper;

AsyncTask就是handler+looper+线程池

AsyncTask在使用的时候并不需要去实例化handler和looper等对象,方便了不少,但是在使用的时候也需要注意:

线程池容量不够抛出异常;
内存泄露;

不过在使用的时候会发现AsyncTask这样子使用一个线程,一个异步任务,有时候并不能满足需要,这个时候可以使用HandlerThread;

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {private SurfaceView surfaceView;private SurfaceHolder surfaceHolder;private HandlerThread camareThread = new HandlerThread("camare_thread");private Handler subHandler;private Camera mCamera;private byte[] buffers;private Handler mainHandler = new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);Log.d("jason4", Thread.currentThread().getName() + "_handleMessage");}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);surfaceView = (SurfaceView) findViewById(R.id.surface_view);surfaceHolder = surfaceView.getHolder();//设置监听回调surfaceHolder.addCallback(this);}class CamareRunnable implements Runnable, Camera.PreviewCallback {@Overridepublic void run() {//打开相机//子线程中打开Log.d("jason1", Thread.currentThread().getName() + "_open");mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);try {mCamera.setPreviewDisplay(surfaceHolder);} catch (IOException e) {e.printStackTrace();}Camera.Parameters parameters = mCamera.getParameters();//设置相机参数parameters.setPreviewSize(480, 320); //预览画面宽高mCamera.setParameters(parameters);//获取预览图像数据buffers = new byte[480 * 320 * 4];mCamera.addCallbackBuffer(buffers);mCamera.setPreviewCallbackWithBuffer(this);mCamera.startPreview();Log.d("jason2", Thread.currentThread().getName() + "_run");}@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {if (mCamera != null) {mCamera.addCallbackBuffer(buffers);//编码Log.d("jason3", Thread.currentThread().getName() + "_onPreviewFrame");mainHandler.sendEmptyMessage(0);}}}@Overridepublic void surfaceCreated(SurfaceHolder holder) {//创建的时候回调//开启HandlerThreadcamareThread.start();//实例化一个handler 将camareThread中的looper设置给subHandlersubHandler = new Handler(camareThread.getLooper());subHandler.post(new CamareRunnable());}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {//改变的时候回调}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {//销毁的时候回调}
}

这是一段简易的开启相机和预览的代码,运行发现jason1、jason2、jason3所打印的都是子线程,只有jason4打印的是主线程;这样子就能一个线程多个任务了;那为什么HandlerThread就可以呢?

/*** Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called.*/

这个是HandlerThread的注释,开启一个线程已经拥有一个Looper,这个Looper可以用来创建一个Handler

所有可以将HandlerThread看作是Thread+Looper;确实HandlerThread 是继承Thread的;

public class HandlerThread extends Thread 
public HandlerThread(String name) {super(name);//name 是指定创建的HandlerThread实例的名称//线程的优先级 一个默认的优先级//最终调用下面那个两个参数的构造方法进行实例化mPriority = Process.THREAD_PRIORITY_DEFAULT;}
    /*** Constructs a HandlerThread.* @param name* @param priority The priority to run the thread at. The value supplied must be from * {@link android.os.Process} and not from java.lang.Thread.*/public HandlerThread(String name, int priority) {super(name);mPriority = priority;}

实例化完毕后调用start()方法开启一个线程;

    
@Overridepublic void run() {//获取当前线程idmTid = Process.myTid();//实例化一个LooperLooper.prepare();synchronized (this) {//获取实例化好的looper并赋值给mLoopermLooper = Looper.myLooper();notifyAll();}//设置线程的优先级Process.setThreadPriority(mPriority);//这个方法可以根据自己的需要去重写,如果想在Looper.loop();之前做一些事情,就可以重写onLooperPrepared();onLooperPrepared();//开始轮询Looper.loop();mTid = -1;}

还提供了quit()、getLooper()等方法,其实HandlerThread的源码并不多;

接下来稍微说下IntentService

public class MyIntentService extends IntentService{/*** Creates an IntentService.  Invoked by your subclass's constructor.** @param name Used to name the worker thread, important only for debugging.*/public MyIntentService(String name) {super(name);}@Overrideprotected void onHandleIntent(Intent intent) {//onHandleIntent方法的回调是在子线程中}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);}@Overridepublic void onDestroy() {super.onDestroy();}
}

IntentService extends Service就是一个Service,但是有不同于其他的Service,其实IntentService就是HandlerThread+Looper+Service;

/*** Creates an IntentService.  Invoked by your subclass's constructor.** @param name Used to name the worker thread, important only for debugging.*/
public IntentService(String name) {super();//和其他的Service不一样,实例化需要传入一个String类型的字符串,该字符串用于子线程中,不过仅用于debuggingmName = name;
}

开启一个Service后,就会根据需要去重写onCreate()、onStart()、onStartCommand()等方法;

    @Overridepublic void onCreate() {// TODO: It would be nice to have an option to hold a partial wakelock// during processing, and to have a static startService(Context, Intent)// method that would launch the service & hand off a wakelock.super.onCreate();//实例化一个HandlerThreadHandlerThread thread = new HandlerThread("IntentService[" + mName + "]");//开启子线程thread.start();//获取HandlerThread中实例化好的LoopermServiceLooper = thread.getLooper();//实例化一个Handler,并将HandlerThread中的Looper作为参数传入,所以ServiceHandler所在的线程也是在子线程中mServiceHandler = new ServiceHandler(mServiceLooper);}

onStartCommand()方法话还是调用的是onStart()方法;

    @Overridepublic void onStart(@Nullable Intent intent, int startId) {//在onStart方法中主要就是通过handler发送了一个消息,不过该消息的发送是在子线程中发送的Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);}

根据handler发送的消息会在ServiceHandler内部类中进行处理;

private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {//消息的处理也是在子线程中,所以onHandleIntent回调是在子线程中onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}}

在onDestory的时候会将Looper移除掉;

    @Overridepublic void onDestroy() {mServiceLooper.quit();}

其实IntentService的作用就是在开启一个服务的时候,刚好如果有耗时操作时,不需要自己开启一个线程或者异步任务去执行该耗时操作,使用IntentService的onHandleIntent()方法中可以直接进行耗时操作。

AsyncTask、HandlerThread、IntentSerivce源码解析相关推荐

  1. HandlerThread和IntentService源码解析

    简介 首先我们先来了解HandlerThread和IntentService是什么,以及为什么要将这两者放在一起分析. HandlerThread: HandlerThread 其实是Handler ...

  2. Handler全家桶之 —— Handler 源码解析

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 本文首发于本人简书 前言 好记性不如烂笔头. 这是一个系列文章,将会包括: Handler全家桶之 -- Handler 源码解析 ...

  3. Handler消息机制(九):IntentService源码解析

    作者:jtsky 链接:https://www.jianshu.com/p/0a150ec09a32 简介 首先我们先来了解HandlerThread和IntentService是什么,以及为什么要将 ...

  4. Handler消息机制(十):HandlerThread源码解析

    作为Android开发者都知道在子线程中使用Handler必须要创建Looper,其实HandlerThread就是在线程中封装了Looper的创建和循环,不用我们开发者自己去创建它,下面我们来看看源 ...

  5. Android之AsyncTask源码解析

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! ##前言 AsyncTask是一种轻量级的异步任务类,内部封装了Thread和Ha ...

  6. AsyncTask源码解析,你需要摸清的细节

    AsyncTask简介 1. AsyncTask提供了一种恰当的简单的跟UI Thread交互的方式. 2. 它不需要通过操控Threads或Handler就可以将后台操作以及其结果展示在UI Thr ...

  7. 【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )

    文章目录 一.线程池作用 二.线程池种类 三.线程池工作机制 四.线程池任务调度源码解析 一.线程池作用 线程池作用 : ① 避免创建线程 : 避免每次使用线程时 , 都需要 创建线程对象 ; ② 统 ...

  8. android sdk 源码解析

    AndroidSdkSourceAnalysis:https://github.com/LittleFriendsGroup/AndroidSdkSourceAnalysis 第一期 Class 分析 ...

  9. Android多线程之IntentService源码解析

    想要了解 IntentService 的工作原理需要先对 Android 系统中以 Handler.Looper.MessageQueue 组成的异步消息处理机制以及 HandlerThread 有所 ...

最新文章

  1. 计算机审计 pdf,计算机审计第三章作业.pdf
  2. Java Stack栈类详解
  3. mysql 取 浮点运算_mysql 浮点型运算误差原因分析及解决方法
  4. 函数参数的传递问题(一级指针和二级指针)
  5. Python 数据分析三剑客之 Pandas(一):认识 Pandas 及其 Series、DataFrame 对象
  6. python爬取天气预报源代码_python抓取天气并分析 实例源码
  7. 如何阅读python文档_python 文档怎么看-问答-阿里云开发者社区-阿里云
  8. python中字符串之间的比较_如何利用python来对比两个字符串的差异
  9. 计算机语言中索引什么意思,index在中是什么意思
  10. 国内云服务商如何排名?国内云主机服务器哪家好?
  11. IntelliJ Keymap
  12. PageHelper自定义count
  13. 上班路上快一倍,长途出门快一半
  14. C和C++不安全?Android 支持 Rust 开发操作系统
  15. 计算机中的right函数,right函数用法实例
  16. 图对比学习的应用(NCL,SimGRACE,ClusterSCL)
  17. 旋转卡(qia)壳 平面最远点对
  18. android 如何获取网络视频的第一帧
  19. VS 和VC 的区别
  20. 修改密码问题_修改密码

热门文章

  1. 定义一个Ladder类用来刻画“梯形”,要求:Ladder类具有类型为double的上底、下底、高、面积属性,具有返回面积的功能。
  2. 洛谷 P5886 Hello, 2020!
  3. sql注入中的union select 1,2,3....
  4. ChatGPT 的 20 种有趣用途,您可能不知道
  5. TypeScript 中的 export 和 import
  6. 春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总的一半。请帮小明找到该红包金额。
  7. python middleware_Django组件之Middleware
  8. 和日本留学同学聊天想到的
  9. conda activate pytorch报错
  10. 不能使用鼠标在vi中实现粘贴功能