Skip to content

Commit f14a05d

Browse files
committed
Update articles
1 parent c83588b commit f14a05d

File tree

8 files changed

+121
-5
lines changed

8 files changed

+121
-5
lines changed

Java/ThreadLocal 原理.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# ThreadLocal 原理
2+
3+
## 概述
4+
5+
- 其作用域覆盖线程,而不是某个具体任务
6+
- 其“自然”的生命周期与线程的生命周期“相同”。Thread 类中有 threadlocal 变量
7+
8+
## 使用场景
9+
10+
- 实现单个线程单例以及单个线程上下文信息存储,比如交易id等
11+
- 实现线程安全,非线程安全的对象使用ThreadLocal之后就会变得线程安全,因为每个线程都会有一个对应的实例
12+
- 承载一些线程相关的数据,避免在方法中来回传递参数
13+
14+
15+
16+
------
17+
18+
[]: https://juejin.im/post/59db31c16fb9a00a4843dc36#heading-4 "源码|ThreadLocal的实现原理"
19+

android/Android Binder机制.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Binder机制
22

3+
## 背景
4+
5+
### Linux IPC
6+
7+
- 管道(单向)
8+
- socket
9+
- 消息队列/共享内存/信号量
10+
311
## Why Binder?
412

513
Android 系统是基于 Linux 内核的,Linux 已经提供了管道、消息队列、共享内存和 Socket 等 IPC 机制。那为什么 Android 还要提供 Binder 来实现 IPC 呢?主要是基于**性能****稳定性****安全性**几方面的原因。
@@ -12,14 +20,20 @@ Android 系统是基于 Linux 内核的,Linux 已经提供了管道、消息
1220

1321
### 稳定性
1422

23+
基于Client-Server的通信方式广泛应用于从互联网和数据库访问到嵌入式手持设备内部通信等各个领域。智能手机平台特别是Android系统中,为了向应用开发者提供丰富多样的功能,这种通信方式更是无处不在,诸如媒体播放,视音频频捕获,到各种让手机更智能的传感器(加速度,方位,温度,光亮度等)都由不同的Server负责管理,应用程序只需做为Client与这些Server建立连接便可以使用这些服务,花很少的时间和精力就能开发出令人眩目的功能。
24+
1525
再说说稳定性,Binder 基于 C/S 架构,客户端(Client)有什么需求就丢给服务端(Server)去完成,架构清晰、职责明确又相互独立,自然稳定性更好。共享内存虽然无需拷贝,但是控制负责,难以使用。从稳定性的角度讲,Binder 机制是优于内存共享的。
1626

1727
### 安全性
1828

29+
Android作为一个开放式,拥有众多开发者的的平台,应用程序的来源广泛,确保智能终端的安全是非常重要的。终端用户不希望从网上下载的程序在不知情的情况下偷窥隐私数据,连接无线网络,长期操作底层设备导致电池很快耗尽等等。传统IPC没有任何安全措施,完全依赖上层协议来确保。首先传统IPC的接收方无法获得对方进程可靠的UID/PID(用户ID/进程ID),从而无法鉴别对方身份。**Android为每个安装好的应用程序分配了自己的UID**,故进程的UID是鉴别进程身份的重要标志。使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标记只有由IPC机制本身在内核中添加。其次传统IPC访问接入点是开放的,无法建立私有通道。比如命名管道的名称,system V的键值,socket的ip地址或文件名都是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。
30+
1931
可靠的身份标识只有由 IPC 机制在内核中添加。其次传统的 IPC 访问接入点是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。同时 Binder 既支持实名 Binder,又支持匿名 Binder,安全性高。
2032

2133
### 总结
2234

35+
**Binder基于Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。**
36+
2337
![img](https://pic3.zhimg.com/80/v2-30dce36be4e6617596b5fab96ef904c6_hd.jpg)
2438

2539
## 进程间通讯
@@ -131,7 +145,9 @@ Binder 是基于 C/S 架构的。由一系列的组件组成,包括 Client、S
131145

132146
#### 区别
133147

134-
Proxy与Stub不一样,虽然他们都既是Binder又是IInterface,**不同的是Stub采用的是继承(is 关系),Proxy采用的是组合(has 关系)**。他们均实现了所有的IInterface函数,不同的是,Stub又使用策略模式调用的是虚函数(待子类实现),而Proxy则使用组合模式。为什么Stub采用继承而Proxy采用组合?事实上,Stub本身is一个IBinder(Binder),它本身就是一个能跨越进程边界传输的对象,所以它得继承IBinder实现transact这个函数从而得到跨越进程的能力(这个能力由驱动赋予)。**Proxy类使用组合,是因为他不关心自己是什么,它也不需要跨越进程传输,它只需要拥有这个能力即可,要拥有这个能力,只需要保留一个对IBinder的引用。**如果把这个过程做一个类比,在封建社会,Stub好比皇帝,可以号令天下,他生而具有这个权利(不要说宣扬封建迷信。。)如果一个人也想号令天下,可以,“挟天子以令诸侯”。为什么不自己去当皇帝,其一,一般情况没必要,当了皇帝其实限制也蛮多的是不是?我现在既能掌管天下,又能不受约束(Java单继承);其二,名不正言不顺啊,我本来特么就不是(Binder),你非要我是说不过去,搞不好还会造反。最后呢,如果想当皇帝也可以,那就是asBinder了。在Stub类里面,asBinder返回this,在Proxy里面返回的是持有的组合类IBinder的引用。
148+
Proxy与Stub不一样,虽然他们都既是Binder又是IInterface,**不同的是Stub采用的是继承(is 关系),Proxy采用的是组合(has 关系)**。他们均实现了所有的IInterface函数,不同的是,Stub又使用策略模式调用的是虚函数(待子类实现),而Proxy则使用组合模式。为什么Stub采用继承而Proxy采用组合?事实上,Stub本身is一个IBinder(Binder),它本身就是一个能跨越进程边界传输的对象,所以它得继承IBinder实现transact这个函数从而得到跨越进程的能力(这个能力由驱动赋予)。
149+
150+
**Proxy类使用组合,是因为他不关心自己是什么,它也不需要跨越进程传输,它只需要拥有这个能力即可,要拥有这个能力,只需要保留一个对IBinder的引用。**如果把这个过程做一个类比,在封建社会,Stub好比皇帝,可以号令天下,他生而具有这个权利(不要说宣扬封建迷信。。)如果一个人也想号令天下,可以,“挟天子以令诸侯”。为什么不自己去当皇帝,其一,一般情况没必要,当了皇帝其实限制也蛮多的是不是?我现在既能掌管天下,又能不受约束(Java单继承);其二,名不正言不顺啊,我本来特么就不是(Binder),你非要我是说不过去,搞不好还会造反。最后呢,如果想当皇帝也可以,那就是asBinder了。在Stub类里面,asBinder返回this,在Proxy里面返回的是持有的组合类IBinder的引用。
135151

136152
------
137153

android/Android IPC.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,24 @@
2020
- **4.单例模式失效**
2121
- **5.数据传递的对象必须可序列化**
2222

23-
## IPC 方法
23+
## 种类
2424

25-
- Messenger(基于AIDL的上层封装)
26-
- AIDL
25+
- Messenger(基于AIDL的上层封装)
26+
- AIDL(基于Binder封装)
27+
- Intent(基于Binder封装)
28+
- Binder(基于Binder封装)
29+
- ContentProvider(基于Binder封装)
2730

2831
### Messenger
2932

3033
- Handler 每次只会处理一个message
3134
- 无法考虑并发的情况
35+
- 只能传输 Bundle 支持的数据类型
3236

37+
## 总结
38+
39+
- 只有允许不同应用的客户端用 IPC 方式调用远程方法,并且想要在服务中处理多线程时,才有必要使用 AIDL
40+
- 如果需要调用远程方法,但不需要处理并发 IPC,就应该通过实现一个 Binder 创建接口
41+
- 如果您想执行 IPC,但只是传递数据,不涉及方法调用,也不需要高并发,就使用 Messenger 来实现接口
42+
- 如果需要处理一对多的进程间数据共享(主要是数据的 CRUD),就使用 ContentProvider
43+
- 如果要实现一对多的并发实时通信,就使用 Socket

android/Android 广播.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Android 广播
2+
3+
## 类型
4+
5+
- 显式广播
6+
7+
发送的Intent是显示Intent的广播。通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,去调用以下方法。意图明确,指定了要激活的组件是哪个组件,一般是在相同的应用程序内部实现的。
8+
9+
- 隐式广播
10+
11+
通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下。Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。一般是用于在不同应用程序之间。
12+
13+
## 机制
14+
15+
- 普通广播
16+
17+
普通广播是完全异步的,通过Context的sendBroadcast()方法来发送,消息传递效率比较高,但所有receivers(接收器)的执行顺序不确定。缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播,直到没有与之匹配的广播接收器为止。
18+
- 有序广播
19+
有序广播通过Context.sendOrderedBroadcast()来发送,所有的广播接收器优先级依次执行,广播接收器的优先级通过receiver的intent-filter中的android:priority属性来设置,数值越大优先级越高。
20+
21+
当广播接收器接收到广播后,可以使用setResult()函数来结果传给下一个广播接收器接收,然后通过getResult()函数来取得上个广播接收器接收返回的结果。
22+
- 系统广播
23+
24+
25+
26+
## 注册
27+
28+
- 静态注册
29+
30+
静态注册是常驻型 ,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
31+
32+
- 动态注册
33+
34+
动态注册广播不是 常驻型广播 ,也就是说广播跟随activity的生命周期。

android/Android 线程间通信.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Android 线程间通信
2+
3+
## 种类
4+
5+
- 单向管道。非 Android 独有
6+
- 共享内通信
7+
- 消费者生产者模型 — BlockingQueue。非 Android 独有
8+
- 消息队列。Handler 机制
9+
10+
11+
12+
## Handler 机制
13+
14+
### Looper
15+
16+
#### Looper.prepare()
17+
18+
![2011091315284989](https://pic002.cnblogs.com/images/2011/315542/2011091315284989.png)
19+
20+
21+
22+
23+
24+
## 总结
25+
26+
- Looper调用prepare()进行初始化,创建了一个与当前线程对应的Looper对象(**通过ThreadLocal实现**),并且初始化了一个与当前Looper对应的MessageQueue对象。
27+
- Looper调用静态方法loop()开始消息循环,通过MessageQueue.next()方法获取Message对象。
28+
当获取到一个Message对象时,让Message的发送者(target)去处理它。
29+
- Message对象包括数据,发送者(Handler),可执行代码段(Runnable)三个部分组成。
30+
- Handler可以在一个已经Looper.prepare()的线程中初始化,如果线程没有初始化Looper,创建Handler对象会失败
31+
一个线程的执行流中可以构造多个Handler对象,它们都往同一个MQ中发消息,消息也只会分发给对应的Handler处理。
32+
- Handler将消息发送到MQ中,Message的target域会引用自己的发送者,Looper从MQ中取出来后,再交给发送这个Message的Handler去处理。
33+
- Message可以直接添加一个Runnable对象,当这条消息被处理的时候,直接执行Runnable.run()方法。
34+

android/Service 总结.md

Whitespace-only changes.

chromium/Chromium 框架简介.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Chromium 框架简介
22

3-
## d
3+
##

other/心得体会.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[]: https://droidyue.com/blog/2017/10/22/to-way-to-learning-android/ "我学习Android的一些套路"
2+

0 commit comments

Comments
 (0)