簡體   English   中英

如何將函數調用限制為特定的線程/執行器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM