【问题标题】:CountDownLatch not freeing threadCountDownLatch 不释放线程
【发布时间】:2016-10-28 16:55:40
【问题描述】:

我有一个从 Firebase 存储加载图像的方法。它在后台线程中调用,我需要阻止它,直到加载图像(以避免回调地狱)。这是代码(在 Kotlin 中)

override fun fromNet(): Bitmap? {
    Log.wtf(TAG, "$name loading from firebase")
    var result: Bitmap? = null
    val lock = CountDownLatch(1)
    try {
        FirebaseStorage.getInstance().getReferenceFromUrl(FIRE_STORAGE).child(ctx.getKGL().famkey)
            .child(name).getBytes(524288L)
            .addOnFailureListener {
                Log.wtf(TAG, "$name load failure")
                lock.countDown()
            }
            .addOnSuccessListener { bytes ->
                Log.wtf(TAG, "$name loaded")
                val b = BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64))
                result = b
                lock.countDown()
                ctx.saveToCache(name, b)
            }
            .addOnCompleteListener {
                Log.wtf(TAG, "on complete")
                lock.countDown()
            }
    } catch (ignored: NullPointerException) { lock.countDown() }
    lock.await()
    return result
}

但是线程永远被阻塞

Logcat:

A/MemberPhoto: xvd6z67gZfMCLG4c9mkGXKe9ML53 load failure
A/MemberPhoto: on complete

UPD:可能是因为 Firebase 代码是 Java,而我的代码是在 Kotlin 中?

【问题讨论】:

  • 好吧,如果在调用lock.countDown() 之前将NullPointerException 抛出到try 块中,lock.await() 将永远不会解除阻塞。不是这样吗?
  • @hotkey 我想,如果抛出异常 - await() 将不会被调用。但是让我检查一下
  • 我的错,我没有在catch 块中发现return null。对不起。
  • 我将 return null 替换为 lock.countdown - 仍然是个问题
  • @NicolasFilotto 如果他在 finally 块中调用lock.countDown(),那么它将永远不会等待。 finally 在他应该等待的主线程上。

标签: java android concurrency kotlin


【解决方案1】:

如果您想确保lock.await() 不会让您当前的线程永远等待,您需要确保无论发生什么都调用lock.countDown(),所以在这里您应该用try/finally 包围您的代码侦听器,以便在 finally 块内调用 lock.countDown()

如果BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64)) 失败,您当前的代码确实是这样,lock.countDown() 将永远不会被调用,这将使调用lock.await() 的线程永远等待。

例如,在成功的情况下,您的侦听器的代码应该是:

.addOnSuccessListener { bytes ->
    try {
        Log.wtf(TAG, "$name loaded")
        val b = BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64))
        result = b
    } finally {
        lock.countDown()
    }        
    ctx.saveToCache(name, b)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 2021-03-27
    • 2016-03-05
    • 2011-09-13
    相关资源
    最近更新 更多