Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package concurrent_hash_map.merge_requests
- import java.util.concurrent.ConcurrentHashMap
- import kotlin.concurrent.thread
- import kotlin.random.Random
- /*Нужно написать имплементацию интерфейсаCommandExecutor.
- При этом нужно сделать так чтобы если мы имели несколько одинаковых запросов одновременно,
- мы выполняли запрос один раз, а не несколько и затем просто дублировали информацию между экранами.
- Метод requestAsync не должен блокировать вызывающий поток,
- а ответ должен приходить в метод onResponse.*/
- interface CommandExecutor {
- fun requestAsync(url: String, onResponse: (String) -> Unit)
- }
- class CommandExecutorImpl : CommandExecutor {
- private val map = ConcurrentHashMap<String, MutableList<(String) -> Unit>>()
- private val requestIsMaking = ConcurrentHashMap<String, Boolean>()
- override fun requestAsync(url: String, onResponse: (String) -> Unit) {
- if (map.contains(url)) {
- map.computeIfPresent(url) { _, v ->
- v.apply { add(onResponse) }
- }
- } else {
- map.putIfAbsent(url, mutableListOf())
- map.computeIfPresent(url) { _, v ->
- v.apply { add(onResponse) }
- }
- if(requestIsMaking.putIfAbsent(url, true) == null) makeRequest(url)
- }
- }
- private fun makeRequest(url: String) {
- println("Make request by ${Thread.currentThread().name} for $url")
- Thread.sleep(Random.nextLong(5000)) // simulate io operation from 0 to 5000 ms
- (map[url] ?: mutableListOf()).forEach { consumer ->
- consumer.invoke("Response for $url")
- }
- }
- }
- fun main() {
- val urls = listOf(
- "url1",
- "url2",
- "url3"
- )
- val commandExecutor = CommandExecutorImpl()
- for(i in 0..10) {
- val urlIndex = Random.nextInt(0, urls.size)
- thread(name = "Thread $i") {
- val threadName = Thread.currentThread().name
- commandExecutor.requestAsync(urls[urlIndex]) {
- println("Consume response by $threadName - $it")
- }
- }
- }
- Thread.sleep(10000)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement