代码之家  ›  专栏  ›  技术社区  ›  Maxim

如何将函数调用限制到特定的线程/执行器

  •  2
  • Maxim  · 技术社区  · 8 年前

    我目前正在为移动应用程序设计数据库。最近我发现在后台访问数据库非常有用的功能:

    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)
    }
    

    然后使用 notInIOThread() 在里面 init() 和 getInstance() 功能

    3 回复  |  直到 8 年前
        1
  •  2
  •   Kiskae    8 年前

    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
    
        2
  •  1
  •   jonathanrz    8 年前

    当你用@workerthread注释一个方法或类时,如果你从用户界面线程调用它,android会给你lint错误。

    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

        3
  •  1
  •   ice1000    8 年前

    ioThread

    class MyDslClass internal constructor() {
        fun init(context: Context) { ... }
        fun getInstance() { ... }
    }
    

    和 应该是:

    fun ioThread(f : MyDslClass.() -> Unit) {
        val dsl = MyDslClass()
        IO_EXECUTOR.execute { dsl.f() }
    }
    

    fun main(args: Array<String>) {
        ioThread {
            getInstance() // Ok
        }
        // cannot call `getInstance` since I cannot construct a `MyDslClass`
    }