可以和ArrayList实现对比下 Android之ArrayList
创新互联专业IDC数据服务器托管提供商,专业提供成都服务器托管,服务器租用,乐山服务器托管,乐山服务器托管,成都多线服务器托管等服务器托管服务。
ArrayList 实现多了一个AccessRondom 接口,少了Deque 接口
LinkList 实现多了Deque接口,少了AccessRandom接口
想了解AccessRandom接口可以参看 AccessRandom接口有啥用
Deque接口顾名思义,队列,说明LinkList 支持队列操作
来看看内部属性
官方文档对LinkList 的解释是双向链表,那么很容易理解这里保留first ,last 指针的意义了,就是为了方便双向遍历和插入
本身添删改查没有太多要说,注意下按索引遍历,先是算下inde与size /2 比较下,然后决定是从头部开始遍历还是尾部开始遍历。
主要就是有一个线程队列,维护这些任务,这里没有用到Queue而是用List是考虑到显示的问题。
当面试官问到你消息对列的时候,恭喜你,已经跨过初级,在试探你的中级水平了。
Android的消息循环是参考Windows的消息循环机制来实现的。
消息队列4件套 Message、MessageQueue、Looper、Handler
1、Message 是消息对列的消息实体类,因为消息队列中会存放最多10个Message对象。常用属性 what,是消息体的Tag,用来区分是那个一消息体。
2、 MessageQueue 先进先出”的原则存放消息,将Message对象以链表的方式串联起来。
3、Looper 是MessageQueue的管理者,主线程中是一对一的关系。子线程需要用到消息对列的话就需要经典二人组 。先调用 Looper.prepare()方法,然后再调用Looper.loop();
4、Handler 是封装和处理Message对象的。
通过源码可知消息走向如下
handler.sendMessage()--handler.sendMessageDelayed()--handler.sendMessageAtTime()--msg.target = this;queue.enqueueMessage==把msg添加到消息队列中
在Android中有主线程和子线程的区分。主线程又称为UI线程,主要是处理一些和界面相关的事情,而子线程主要是用于处理一些耗时比较大的一些任务,例如一些网络操作,IO请求等。如果在主线程中处理这些耗时的任务,则有可能会出现ANR现象(App直接卡死)。
线程池,从名字的表明含义上我们知道线程池就是包含线程的一个池子,它起到新建线程、管理线程、调度线程等作用。
既然Android中已经有了线程的概念,那么为什么需要使用线程池呢?我们从两个方面给出使用线程池的原因。
在Android中线程池就是ThreadPoolExecutor对象。我们先来看一下ThreadPoolExecutor的构造函数。
我们分别说一下当前的几个参数的含义:
第一个参数corePoolSize为 核心线程数 ,也就是说线程池中至少有这么多的线程,即使存在的这些线程没有执行任务。但是有一个例外就是,如果在线程池中设置了allowCoreThreadTimeOut为true,那么在 超时时间(keepAliveTime) 到达后核心线程也会被销毁。
第二个参数maximumPoolSize为 线程池中的最大线程数 。当活动线程数达到这个数后,后续添加的新任务会被阻塞。
第三个参数keepAliveTime为 线程的保活时间 ,就是说如果线程池中有多于核心线程数的线程,那么在线程没有任务的那一刻起开始计时,如果超过了keepAliveTime,还没有新的任务过来,则该线程就要被销毁。同时如果设置了allowCoreThreadTimeOut为true,该时间也就是上面第一条所说的 超时时间 。
第四个参数unit为 第三个参数的计时单位 ,有毫秒、秒等。
第五个参数workQueue为 线程池中的任务队列 ,该队列持有由execute方法传递过来的Runnable对象(Runnable对象就是一个任务)。这个任务队列的类型是BlockQueue类型,也就是阻塞队列,当队列的任务数为0时,取任务的操作会被阻塞;当队列的任务数满了(活动线程达到了最大线程数),添加操作就会阻塞。
第六个参数threadFactory为 线程工厂 ,当线程池需要创建一个新线程时,使用线程工厂来给线程池提供一个线程。
第七个参数handler为 拒绝策略 ,当线程池使用有界队列时(也就是第五个参数),如果队列满了,任务添加到线程池的时候的一个拒绝策略。
可以看到FixedThreadPool的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出FixedThreadPool的几个特点:
可以看到CacheThreadPool的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出CacheThreadPool的几个特点:
可以看到ScheduledThreadPoolExecutor的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出ScheduledThreadPoolExecutor的几个特点:
可以看到SingleThreadExecutor的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出SingleThreadExecutor的几个特点:
什么是 Handler 机制 ?
Handler 机制是 Android 中用于 线程间通信 的一套通信机制。
为什么是 Handler ?Handler 机制为什么被那么多次的提及 ?
从Android4.0开始,Android 中网络请求强制不允许在主线程中操作,而更新UI的操作则不允许在子线程中执行。当在子线程中执行网络请求,拿到服务器返回的数据之后,要更新UI。由于系统的要求,势必会产生一种矛盾:数据在子线程,更新UI要在主线程。此时我们必须要把数据返回到主线程中才行,Handler机制应运而生。
Android 中针对耗时的操作,放在主线程操作,轻者会造成 UI 卡顿,重则会直接无响应,造成 Force Close。同时在 Android 3.0 以后,禁止在主线程进行网络请求。
针对耗时或者网络操作,那就不能在主线程进行直接操作了,需要放在子线程或者是工作线程中进行操作,操作完成以后,再更新主线程即 UI 线程。这里就涉及到一个问题了,在子线程执行完成以后,怎么能更新到主线程即 UI 线程呢,针对以上问题,就需要用到 Android 的消息机制了,即: Handler, Message, MessageQueue, Looper 全家桶
Handler机制中最重要的四个对象
Handler的构造方法:
Looper :
Handler的使用:
MessageQueue:
Looper.loop()
Handler.dispatchMessage()
handler导致activity内存泄露的原因:
handler发送的消息在当前handler的消息队列中,如果此时activity finish掉了,那么消息队列的消息依旧会由handler进行处理,若此时handler声明为内部类(非静态内部类),我们知道内部类天然持有外部类的实例引用,这样在GC垃圾回收机制进行回收时发现这个Activity居然还有其他引用存在,因而就不会去回收这个Activity,进而导致activity泄露。
假如在子线程执行了耗时操作,这时用户操作进入了其他的 acitvity, 那么 MainActivity 就会被内存回收的,但是这个时候发现 Handler 还在引用着 MainActivity,内存无法及时回收,造成内存泄漏。
Handler 防止内存泄漏常见方法:
为什么通过 Handler 可以把子线程的结果通知或者携带给 UI 线程 ?
这里的 Handler 指的是主线程的 Handler ,同时与 Handler 配套的 Looper , MessageQueue 是在 UI 线程初始化的,所以在子线程中调用 Handler 发送消息可以更新 UI 线程。
Looper 在 UI 线程源码, 在 ActivityThread 类:
文章标题:android队列,Android队列实战例子
链接分享:https://www.cdcxhl.com/article30/dsgciso.html
成都网站建设公司_创新互联,为您提供电子商务、网站内链、静态网站、ChatGPT、定制网站、虚拟主机
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联