CountDownLatch不释放线程 [英] CountDownLatch not freeing thread

查看:731
本文介绍了CountDownLatch不释放线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a method, which loading image from Firebase Storage. It's called in background thread, and I need to block it, until image is loaded (to avoid callback hell). Here is the code (in 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
}

但是线程永远永远被阻塞

But thread stays blocked forever

Logcat:

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

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

UPD: May the cause be, that Firebase code is Java, and my code is in Kotlin?

推荐答案

如果要确保lock.await()不会使当前线程永远等待,则需要确保在发生任何情况时都调用lock.countDown().在这里,您应该在try/finally块周围加上侦听器的代码,以便在finally块中调用lock.countDown().

If you want to be sure that lock.await() won't make your current thread wait forever, you need to ensure that lock.countDown() is called whatever happens so here you should surround with a try/finally block the code of your listeners in order to call lock.countDown() within a finally block.

实际上与您当前的代码有关,例如,如果BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64))失败,则将永远不会调用lock.countDown(),这将使调用lock.await()的线程永远等待.

Indeed otherwise with your current code if for example BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64)) fails, lock.countDown() will never be called which will make the thread calling lock.await() wait forever.

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

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

这篇关于CountDownLatch不释放线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆