![](/style/images/good.png)
![](/style/images/bad.png)
ThreadLocal:你不知道的优化技巧,Android开发者都在用
source link: http://www.rousetime.com/2024/01/09/ThreadLocal%EF%BC%9A%E4%BD%A0%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84%E4%BC%98%E5%8C%96%E6%8A%80%E5%B7%A7%EF%BC%8CAndroid%E5%BC%80%E5%8F%91%E8%80%85%E9%83%BD%E5%9C%A8%E7%94%A8/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
ThreadLocal:你不知道的优化技巧,Android开发者都在用
在Android
开发中,多线程是一个常见的话题。为了有效地处理多线程的并发问题,Android
提供了一些工具和机制。其中,ThreadLocal
是一个强大的工具,它可以使得每个线程都拥有自己独立的变量副本,从而避免了线程安全问题。
本文将深入探讨Android中的ThreadLocal
原理及其使用技巧, 帮助你更好的理解和使用ThreadLocal
。
ThreadLocal的原理
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
ThreadLocal
的原理是基于每个线程都有一个独立的ThreadLocalMap
对象。ThreadLocalMap
对象是一个Map
,它的键是ThreadLocal
对象,值是ThreadLocal
对象保存的值。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
当我们调用ThreadLocal
的set()
方法时,会将值存储到当前线程的ThreadLocalMap
对象中。当我们调用ThreadLocal
的get()
方法时,会从当前线程的ThreadLocalMap
对象中获取值。
ThreadLocal的使用
使用ThreadLocal
非常简单,首先需要创建一个ThreadLocal
对象,然后通过set
和get
方法来设置和获取线程的局部变量。以下是一个简单的例子:
val threadLocal = ThreadLocal<String>()
fun setThreadName(name: String) {
threadLocal.set(name)
}
fun getThreadName(): String {
return threadLocal.get() ?: "DefaultThreadName"
}
在Android
开发中,ThreadLocal
的使用场景非常多,比如:
- 在
Activity
中存储Fragment
的状态 - 在
Handler
中存储消息的上下文 - 在
RecyclerView
中存储滚动位置
实际应用场景
// 在 Activity 中存储 Fragment 的状态
class MyActivity : AppCompatActivity() {
private val mFragmentState = ThreadLocal<FragmentState>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
// 获取 Fragment 的状态
val fragmentState = mFragmentState.get()
if (fragmentState == null) {
// 初始化 Fragment 的状态
fragmentState = FragmentState()
}
// 设置 Fragment 的状态
mFragmentState.set(fragmentState)
// 创建 Fragment
val fragment = MyFragment()
fragment.arguments = fragmentState.toBundle()
supportFragmentManager.beginTransaction().add(R.id.container, fragment).commit()
}
}
class FragmentState {
var name: String? = null
var age: Int? = null
fun toBundle(): Bundle {
val bundle = Bundle()
bundle.putString("name", name)
bundle.putInt("age", age)
return bundle
}
}
这段代码在Activity
中使用ThreadLocal
来存储Fragment
的状态。当Activity
第一次启动时,会初始化Fragment
的状态。当Activity
重新启动时,会从ThreadLocal
中获取Fragment
的状态,并将其传递给Fragment
。
- 内存泄漏风险:
ThreadLocal
变量的生命周期与线程的生命周期是一致的。这意味着,如果一个线程一直不结束,那么它所持有的ThreadLocal
变量也不会被释放。这可能会导致内存泄漏。
为了避免内存泄漏,我们应该在不再需要ThreadLocal
变量时,显式地将其移除。
threadLocal.remove()
- 不适合全局变量:
ThreadLocal
适用于需要在线程间传递的局部变量,但不适合作为全局变量的替代品。
- 合理使用默认值: 在获取
ThreadLocal
值时,可以通过提供默认值来避免返回null
,确保代码的健壮性。
fun getThreadName(): String {
return threadLocal.get() ?: "DefaultThreadName"
}
- 懒加载初始化: 避免在声明
ThreadLocal
时就初始化,可以使用initialValue
方法进行懒加载,提高性能。
val threadLocal = object : ThreadLocal<String>() {
override fun initialValue(): String {
return "DefaultValue"
}
}
- 尽量避免在
ThreadLocal
中保存大对象
在本文中,我们介绍了ThreadLocal
的原理和使用技巧,希望这些知识能够帮助你更好地理解和使用它。
android_startup: 提供一种在应用启动时能够更加简单、高效的方式来初始化组件,优化启动速度。不仅支持Jetpack App Startup的全部功能,还提供额外的同步与异步等待、线程控制与多进程支持等功能。
AwesomeGithub: 基于Github的客户端,纯练习项目,支持组件化开发,支持账户密码与认证登陆。使用Kotlin语言进行开发,项目架构是基于JetPack\&DataBinding的MVVM;项目中使用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等流行开源技术。
flutter_github: 基于Flutter的跨平台版本Github客户端,与AwesomeGithub相对应。
android-api-analysis: 结合详细的Demo来全面解析Android相关的知识点, 帮助读者能够更快的掌握与理解所阐述的要点。
daily_algorithm: 每日一算法,由浅入深,欢迎加入一起共勉。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK