Android消息机制和多线程

一、Android消息机制
Android消息机制主要是指Handle的运行机制,Handle是Android消息机制的上层接口,Handle的运行需要底层的MessageQueue和Looper支撑。
Handle的主要作用是将一个任务切换到指定线程去执行;
MessageQueue内部存储了一组消息,以队列的形式对外提供插入和删除;
Looper以无限循环的形式去查找是否有新消息,如果有就处理消息,否则就一直等待;
Handle创建的时候会采用当前线程的Looper来构造消息循环系统,线程是默认没有Looper的,如果要使用Handler就必须为线程创建Looper,UI线程被创建时就会初始化Looper,使用ThreadLocal可以轻松获取每个线程的Looper,ThreadLocal可以在不同的线程中互不干扰的存储并提供数据。
工作过程:
通过Handler的post将一个Runnable投递到Handler内部中的Looper去处理,也可以通过send方法发送一个消息,这个消息同样会在Looper中去处理。
send方法被调用时,会调用MessageQueue的enqueueMessage方法将这个消息放入消息队列中,然后Looper发现有新消息到来,就会处理这个消息,最终消息中的Runnable或者Handler的handleMessage方法就会被调用。Looper是运行在创建Handler所在的线程中的。
ThreadLocal的工作原理:
ThreadLocal是一个线程内部的数据存储类,通过它可以在指定线程中存储数据,数据存储后,只有在指定线程中可以获取到存储的数据。
不同线程访问同一个ThreadLocal对象,通过ThreadLocal获取到的值是不一样的,因为不同线程访问同一个ThreadLocal的get方法,ThreadLocal内部会从各自的线程中取出一个数组,然后再从数组中根据当前ThreadLocal的索引去查找对应的value值。
消息队列的工作原理:
MessageQueue主要有两个方法enqueueMessage和next,enqueueMessage的作用是往消息中插入一条信息,next的作用是从消息队列中取出一条信息并将其从消息队列中移除,next是一个无限循环的方法,如果消息队列中没有消息,那么next方法会一直阻塞在这里
looper的工作原理
通过Looper.prepare()即可为当前线程创建一个Looper,通过Looper.loop()开启消息循环。loop()方法是一个死循环,唯一跳出循环的方式是MessageQueue的next方法返回了null。
如果在子线程中手动创建了Looper,在所有事情完成后应该调用quit方法来终止消息,否则这个子线程就会一直处于等待状态。
Handler的工作原理
Handler的工作主要包括消息的发送和接收过程。消息的发送可以通过一系列的post方法和一系列的send方法来实现,post方法最终是通过send的一系列方法来实现的。
Handler发送消息的过程仅仅是向消息队列中插入了一条信息,消息队列的next方法就会返回这条消息给Looper,Looper收到消息交给Handler处理:
Handler首先检查Message的callback是否为null,不为null就通过handleCallback来处理消息,Message的callback是一个Runnable对象,实际上就是post放啊所传递的Runnable参数;
其次检查mCallback是否为null,不为null就调用mCallback的handleMessage方法来处理消息;
通过Callback可以采用如下方式来创建Handler实例而不需要派生Handler的子类

Handler handler = new Handler(callback);

最后调用Handler的handleMessage方法来处理消息。
Handler还有一个特殊的构造方法,通过一个特定的Looper来构造Handler
二、Handler的使用
1.Handler分发Runnable对象到主线程
Handler.post(Runnable)
Handler.postAtTime(Runnable,long)
Handler.postDelayed(Runnable,long)
2.View分发Runnable对象
View.post(Runnable)
View.postAtTime(Runnable,long)
View.postDelayed(Runnable,long)
3.Handler分发Message对象到主线程
Handler.sendEmptyMessage(int)
Handler.sendMessage(Message)
Handler.sendMessageAtTime(Message,long)
Handler.sendMessageDelayed(Message,long)
4.Acitivity的runOnUiThread方法
Activity.runOnUiThread(Runnable);
三、AsyscTask
AsycTask是一种轻量级的异步任务类,封装了线程池和Handler,在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。
AsyncTask的对象必须在主线程中创建,execute方法必须在主线程调用。
不适合执行特别耗时的后台任务,对于特别耗时的任务建议使用线程池。
AsyncTask是一个抽象的泛型类,提供了Params、Progress、Result三个泛型参数,Params表示参数的类型,Progress表示后台任务执行进度的类型,Result表示后台任务的返回结果类型。
1)onPreExecute() 主线程执行,异步任务执行之前调用,做一些准备操作;
2)doInBackground(Params…params)线程池中执行,用于执行异步任务,此方法中可以通过publishProgress方法调用onProgressUpdate方法来更新任务的进度,返回计算结果给onPostExecute方法。
3)onProgressUpdate(Progress…values)主线程执行,后台任务执行进度发生变化时此方法调用
4)onPostExecute(Result…result)主线程执行,异步任务执行后执行,result参数是后台任务的返回值
5)onCancelled()主线程执行,当异步任务被取消时被调用
四、HandlerThread
HandlerThread继承了Thread,它是一种可以使用Handler的Thread,在run方法中通过Looper.prepare()创建Looper对象,并通过Looper.loop()来开启消息循环。
普通Thread主要用于在run方法中执行一个耗时任务,而HandlerThread在内部创建了消息队列
五、线程池
线程池的概念源于Java的Executor,Executor是一个接口,真正的线程池实现为ThreadPoolExecutor。ThreadPoolExecutor的构造方法提供了一系列参数来配置线程池。

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory)
  • corePoolSize:线程池维护的核心线程数,核心线程在线程池中会一直存活,即使它们处于闲置状态,如果将allowCoreThreadTimeOut属性设为true,那么闲置的核心线程也会有超时策略
  • maximumPoolSize:线程池维护线程的最大数量,当活动线程达到这个数量,后续新任务会被阻塞
  • keepAliveTime:线程池维护线程所允许的空闲时间,超过这个时间,非核心线程会被回收,如果将allowCoreThreadTimeOut属性设为true,同样会作用于核心线程
  • unit:线程池维护线程线程所允许的空闲时间单位
  • workQueue:线程池所使用的缓冲队列,通过线程池的execute方法提交的Runnable对象会存储在这个参数中
  • threadFactory:线程工厂,为线程池提供创建新线程的功能
    ThreadPoolExecutor执行任务时大致遵循的规则:
    1)如果此时线程池中的线程数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理
    2)如果此时线程池中的线程数量大于或等于corePoolSize,并且缓冲队列workQueue未满,那么任务放入缓冲队列
    3)如果线程数量等于或大于corePoolSize,但小于maximumPoolSize,缓冲队列已满,创建新的线程来处理新添加的任务
    4)如果线程数量等于maximumPoolSize,且缓冲队列已满,那么通过handle所指定的策略来处理任务
    即任务处理的优先级为:corePoolSize,workQueue,maximumPoolSIze,如果三者都满了,则交给handle处理被拒绝的任务
    当线程池中国线程的数量大于corePoolSize时,如果某线程空闲时间大于keepAliveTime,线程将被终止
    线程池的分类:
    1.FixedThreadPool:
    通过Executor的newFixedThreadPool方法来创建,线程数固定。
    只有核心线程并且这些核心线程不会被回收,能够更加快速的响应外界的请求。
    2.CachedThreadPool:
    通过Executor的newCacheThreadPool方法来创建,线程数不定。
    只有非核心线程,并且最大线程数为Integer.MAX_VALUE,任务对垒就相当于一个空集合,空闲线程的超时时长为60秒,适合执行大量的耗时较少的任务。
    3.ScheduledThreadPool
    通过Executor的ScheduledThreadPool方法来创建,核心线程数固定,非核心线程数没有限制。主要用于执行定时任务和具有固定周期的重复任务。
    4.SingleThreadExecutor
    通过Executor的newSingleThreadExecutor方法来创建,内部只有一个核心线程。确保所有的任务都在一个线程中按顺序执行,统一所有的外界任务到一个线程中,使得这些任务不需要处理线程同步的问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值