面试题答案
一键面试确保线程安全及优化资源加载与释放的方法
- 使用
Synchronized
关键字:在访问委托属性和延迟初始化资源的方法上使用synchronized
关键字,以确保同一时间只有一个线程可以访问这些资源。 - 使用
ReentrantLock
:ReentrantLock
提供了更灵活的锁机制,可以替代synchronized
关键字,特别是在需要更复杂的锁控制时。 - 使用
Atomic
类型:对于简单的原子操作,可以使用Atomic
类型的变量,如AtomicBoolean
、AtomicInteger
等,以避免使用锁带来的性能开销。 - 使用线程安全的集合类:如果委托属性或延迟初始化资源涉及到集合类,应使用线程安全的集合类,如
ConcurrentHashMap
、CopyOnWriteArrayList
等。
代码示例
以下是一个使用委托属性和延迟初始化管理资源,并确保线程安全的Android代码示例:
import java.util.concurrent.locks.ReentrantLock
import kotlin.properties.Delegates
class MyResource {
// 模拟资源加载
fun load() {
println("Resource loaded")
}
// 模拟资源释放
fun release() {
println("Resource released")
}
}
class MyViewModel {
private val lock = ReentrantLock()
private var _resource: MyResource? = null
val resource: MyResource by lazy {
lock.lock()
try {
if (_resource == null) {
_resource = MyResource()
_resource?.load()
}
_resource!!
} finally {
lock.unlock()
}
}
fun releaseResource() {
lock.lock()
try {
_resource?.release()
_resource = null
} finally {
lock.unlock()
}
}
}
代码解释
MyResource
类:代表需要管理的资源,包含load
和release
方法来模拟资源的加载和释放。MyViewModel
类:lock
:定义一个ReentrantLock
实例,用于线程同步。_resource
:一个可空的MyResource
变量,用于存储实际的资源实例。resource
:使用lazy
委托属性延迟初始化资源。在初始化过程中,首先获取锁,然后检查资源是否已经初始化。如果未初始化,则创建并加载资源,最后返回资源实例。使用finally
块确保无论是否发生异常,锁都会被释放。releaseResource
:用于释放资源的方法。同样,在方法开始时获取锁,释放资源并将_resource
设置为null
,最后在finally
块中释放锁。
通过这种方式,可以确保在多线程环境下,资源的加载与释放是线程安全的,并且通过延迟初始化优化了资源的使用。