[英]How to restrict function invocation to a particular thread/executor
我目前正在為移動應用程序設計數據庫。 最近,我發現在后台訪問數據庫非常有用的功能:
private val IO_EXECUTOR = Executors.newSingleThreadExecutor()
fun ioThread(f : () -> Unit) {
IO_EXECUTOR.execute(f)
}
除此之外,我還發現不需要同步代碼,因為數據庫只能在一個線程(即SingleThreadExecutor
使用的線程)中訪問。
唯一的問題是必須限制以下方法只能通過ioThread
函數(或使用IO_EXECUTOR
)調用。
abstract class MyDatabase : RoomDatabase() {
companion object {
fun init(context: Context) { ... }
fun getInstance() { ... }
}
是否可以在Kotlin
/ Java
實現這一目標?
更新:目前我有此實現,但認為應該有更好的實現
// App.kt file
private val IO_EXECUTOR = Executors.newSingleThreadExecutor()
private var IO_THREAD_ID: Long = -1L
private fun getIOThreadId(): Long {
if (IO_THREAD_ID == -1L)
IO_THREAD_ID = IO_EXECUTOR.submit(Callable<Long> { Thread.currentThread().id }).get()
return IO_THREAD_ID
}
fun notInIOThread() = Thread.currentThread().id != getIOThreadId()
fun ioThread(f : () -> Unit) {
IO_EXECUTOR.execute(f)
}
然后在init()
和getInstance()
函數中使用notInIOThread()
如果絕對需要確保代碼在正確的線程上運行,則可以使用自定義線程,然后檢查該接口的Thread.currentThread()
。
private interface MarkedIOThread // Marker interface
private val IO_EXECUTOR = Executors.newSingleThreadExecutor { r ->
return object : Thread(r), MarkedIOThread
}
fun notInIOThread(): Boolean = Thread.currentThread() !is MarkedIOThread
是的,您可以使用android注解的Worker Thread注解。
當您使用@WorkerThread注釋方法或類時,如果您從UI線程調用它,android將會給您提供lint錯誤。
您可以在此處閱讀有關@WorkerThread的更多信息: https : //developer.android.com/reference/android/support/annotation/WorkerThread
以及有關android批注的更多信息: https : //developer.android.com/studio/write/annotations
我建議您應該檢查房間庫: https : //developer.android.com/topic/libraries/architecture/room
它非常強大,如果您沒有創建數據庫庫的特定原因,那么最好的選擇就是空間。
我假設您只希望在ioThread
代碼塊內部調用這些函數,否則會出現類型錯誤。 首先,使用用戶代碼不可訪問的構造函數使它們成為類的成員函數,以便其他人無法直接調用它:
class MyDslClass internal constructor() {
fun init(context: Context) { ... }
fun getInstance() { ... }
}
ioThread
應該是:
fun ioThread(f : MyDslClass.() -> Unit) {
val dsl = MyDslClass()
IO_EXECUTOR.execute { dsl.f() }
}
然后,您可以僅在ioThread
塊內限制對這些函數的調用。
fun main(args: Array<String>) {
ioThread {
getInstance() // Ok
}
// cannot call `getInstance` since I cannot construct a `MyDslClass`
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.