If you are required to work with ThreadLocals, wou...
# announcements
b
If you are required to work with ThreadLocals, would that be a good idea or not:
Copy code
class ThreadlocalDelegate<E>(initializer: ()->E) {
    private val threadLocal = ThreadLocal.withInitial(initializer)

    operator fun getValue(thisRef: Any?, property: KProperty<*>): E {
        return threadLocal.get()
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: E) {
        threadLocal.set(value)
    }
}

fun <E> threadlocal(initializer: ()->E) = ThreadlocalDelegate(initializer)

fun main() {

    val sdf by threadlocal { SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
        timeZone = TimeZone.getTimeZone("UTC")
    }}

    for(i in 0 until 10 ) {
        thread {
            println("${Thread.currentThread().name} - ${System.identityHashCode(sdf)}) - ${sdf.format(Date())}")
        }
    }

}
k
Looks like a perfect application of delegates to me!
c
Not an answer, but some useful info about slack 🙂 ` ``` ` for multi-line code:
👍 2
Copy code
L1
L2
L3
@Czar Now I wonder why single line code is actually red at all...
c
or is it?
k
How did you do that?
c
k
Will look into that, thanks!
d
Small optimization with extension functions instead,
Copy code
operator fun <E> ThreadLocal<E>.getValue(thisRef: Any?, property: KProperty<*>): E {
    return get()
}

operator fun <E> ThreadLocal<E>.setValue(thisRef: Any?, property: KProperty<*>, value: E) {
    set(value)
}

fun main() {
    val sdf by ThreadLocal.withInitial { SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
        timeZone = TimeZone.getTimeZone("UTC")
    }}

    for(i in 0 until 10 ) {
        thread {
            println("${Thread.currentThread().name} - ${System.identityHashCode(sdf)}) - ${sdf.format(Date())}")
        }
    }
}
d
If you want to optimize it, extend
ThreadLocal
, override
initialValue()
and use a
crossinline
lambda there. ;) As for whether it's a good idea - theres a reason why this doesn't exist in the standard library, which is that there is no way to clear the value (cleaning up your resources from the ThreadLocalMap of the thread once you're done) unless you have access to the delegate instance, instead of just the getter. Unless you make the type nullable, but I would advise against that.