AIDL数据传递 CopyOnWriteArrayList

来源:互联网 发布:java hmacmd5 编辑:程序博客网 时间:2024/06/06 10:00

在Android的AIDL编程中,服务端支持的数据类型有:

基本数据类型(int, long, char, boolean, double)String和CharSequenceList:只支持ArrayListMap:只支持HashMapParcelable:所有实现了parcelable接口的对象AIDL:所有的AIDL接口本身也可以在AIDL中使用

线程同步问题
在这里要注意一下,AIDL方法是在服务端的Binder线程池中执行的,因此多个客户端同时连接的时候,会存在多线程同步的问题,而List和Map是线程不安全的,所以可以使用CopyOnWriteArrayList这个类型来实现线程同步。 虽然前面说,AIDL中能够使用的基本类型是List,其实AIDL支持的是抽象的List,而List是一个接口,因此虽然服务端返回的是CopyOnWriteArrayList,但是在Binder中会按照List的规范去访问数据并最终形成一个ArrayList传递给客户,与此相似的是ConcurrentHashMap。

CopyOnWriteArrayList
关于CopyOnWriteArrayList,CopyOnWriteArrayList类最大的特点就是,在对其实例进行修改操作(add/remove等)会新建一个数据并修改,修改完毕之后,再将原来的引用指向新的数组。这样,修改过程没有修改原来的数组。也就没有了ConcurrentModificationException错误。 CopyOnWriteArrayList是ArrayList 的一个线程安全的变体,ArrayList实现了RandomAccess接口,表明其支持快速的随机访问。读的时候就是在引用的当前对象上进行读(包括 get,iterator等),不存在加锁和阻塞,针对iterator使用了一个叫COWIterator 的阉割版迭代器,因此不支持写操作,当获取CopyOnWriteArrayList的迭代器时,是将迭代器里的数据引用指向当前引用指向的数据对象,无 论未来发生什么写操作,都不会再更改迭代器里的数据对象引用,所以迭代器也很安全。CopyOnWriteArrayList中写操作需要大面积复制数 组,所以性能肯定很差,读操作和写操作针对的不是同一个对象,所以读之间也不需要加锁,读和写之间的同步处理只是在写完后通过一个简单的“=”将引用指向 新的数组对象上来。适合使用在读操作远远大于写操作的。
ConcurrentHashMap
ConcurrentHashMap引入了Segment,每个Segment又是一个hashtable,相当于是两级Hash表,然后锁是在 Segment一级进行的,提高了并发性。缺点是对整个集合进行操作的方法如 size() 或 isEmpty()的实现很困难,基本无法得到精准的数据。Segment的read不加锁,只有在读到null的情况(一般不会有null的,只有在其 他线程操作Map的时候,所以就用锁来等他操作完)下调用了readValueUnderLock。数据存储是采用hash表的方式将元素分布在各 bucket之间,当遍历一个hash表的bucket以期找到某一特定的key时, get() 必须对大量的候选bucket调用 Object.equals() 。如果key类所使用的 hashCode() 函数不能将value均匀地分布在整个hash表范围内,或者存在大量的hash冲突,那么某些bucket链就会比其他的链长很多,而遍历一个长的 hash链以及对该hash链上一定百分比的元素调用 equals() 是一件很慢的事情,所以会影响迭代效率。

原创粉丝点击