Skip to content

Commit

Permalink
update: use ThreadLocal replace for InheritableThreadLocal
Browse files Browse the repository at this point in the history
  • Loading branch information
muedsa committed Jan 12, 2024
1 parent 7083056 commit cc556f6
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -1,54 +1,45 @@
package com.muedsa.snapshot.tools

import java.net.URL
import kotlin.concurrent.getOrSet
import java.util.concurrent.ConcurrentHashMap

object SimpleNoLimitedNetworkImageCache : NetworkImageCache {

var debug: Boolean = false

const val NAME: String = "SimpleNoLimitedNetworkImageCache"

private val threadLocalCache: InheritableThreadLocal<MutableMap<String, ByteArray>> = InheritableThreadLocal()

private val cache: MutableMap<String, ByteArray>
@Synchronized
get() = threadLocalCache.getOrSet { mutableMapOf() }
private val threadLocalCache: ThreadLocal<MutableMap<String, ByteArray>> = ThreadLocal.withInitial {
ConcurrentHashMap()
}

override val name: String
get() = NAME

@Synchronized
override fun getImage(url: String): ByteArray {
if (debug) println("Thread[${Thread.currentThread().name}] try get image from cache: $url")
return cache.getOrPut(url) {
return threadLocalCache.get().computeIfAbsent(url) {
if (debug) println("Thread[${Thread.currentThread().name}] not found in cache: $url")
getImageOverHttp(url)
}
}

@Synchronized
override fun clearAll() {
cache.clear()
threadLocalCache.get().clear()
}

@Synchronized
override fun clearImage(url: String) {
cache.remove(url)
threadLocalCache.get().remove(url)
}

@Synchronized
override fun count(): Int = cache.size
override fun count(): Int = threadLocalCache.get().size

@Synchronized
override fun size(): Int = cache.values.fold(0) { acc: Int, bytes: ByteArray ->
override fun size(): Int = threadLocalCache.get().values.fold(0) { acc: Int, bytes: ByteArray ->
acc + bytes.size
}

private fun getImageOverHttp(url: String): ByteArray {
if (debug) println("Thread[${Thread.currentThread().name}] request http image: $url")
return URL(url).openStream().use { it.readAllBytes() }
}


}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.muedsa.snapshot.tools

import java.util.concurrent.Semaphore
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.expect
Expand Down Expand Up @@ -60,53 +59,21 @@ class SimpleNoLimitedNetworkImageCacheTest {

@Test
fun multi_thread_test(){
expect(0) {
SimpleNoLimitedNetworkImageCache.count()
}
SimpleNoLimitedNetworkImageCache.getImage(TEST_IMAGE_URL_1)
SimpleNoLimitedNetworkImageCache.getImage(TEST_IMAGE_URL_2)
val thread1 = Thread {
expect(2) {
SimpleNoLimitedNetworkImageCache.count()
}
SimpleNoLimitedNetworkImageCache.getImage(TEST_IMAGE_URL_3)
expect(3) {
SimpleNoLimitedNetworkImageCache.count()
}
}
thread1.start()
thread1.join()
expect(3) {
SimpleNoLimitedNetworkImageCache.count()
}
val semaphore = Semaphore(0)
val thread2 = Thread {
semaphore.acquire()
expect(1) {
SimpleNoLimitedNetworkImageCache.count()
}
SimpleNoLimitedNetworkImageCache.clearAll()
}
thread2.start()
SimpleNoLimitedNetworkImageCache.clearAll()
SimpleNoLimitedNetworkImageCache.getImage(TEST_IMAGE_URL_4)
semaphore.release()
thread2.join()
expect(0) {
SimpleNoLimitedNetworkImageCache.count()
}

val resultArr = IntArray(10)
val threadArr = Array(10) {
Thread {
resultArr[it] = SimpleNoLimitedNetworkImageCache.getImage(RANDOM_IMAGE_URL).hashCode()
getImage_test()
}
}
threadArr.forEach { it.start() }
threadArr.forEach { it.join() }
resultArr.forEach {
assert(it != 0)
assert(it == resultArr[0])
}

@Test
fun size_test() {
val size = SimpleNoLimitedNetworkImageCache.getImage(TEST_IMAGE_URL_2).size +
SimpleNoLimitedNetworkImageCache.getImage(TEST_IMAGE_URL_3).size
expect(size) {
SimpleNoLimitedNetworkImageCache.size()
}
}

Expand All @@ -121,6 +88,5 @@ class SimpleNoLimitedNetworkImageCacheTest {
const val TEST_IMAGE_URL_3 = "https://pic4.zhimg.com/v2-7d91b996e9523b572f63b295d446031f_400x224.jpg"
const val TEST_IMAGE_URL_4 = "https://pic1.zhimg.com/80/v2-ba7c92d4371c4a9646ee5478aedb3a31_400x224.webp?source=1def8aca"
const val TEST_IMAGE_URL_5 = "https://pica.zhimg.com/80/v2-78319dbd88aea48d571aa05ca6d53fac_400x224.webp?source=1def8aca"
const val RANDOM_IMAGE_URL = "https://picsum.photos/200/300"
}
}

0 comments on commit cc556f6

Please sign in to comment.