Created
April 20, 2023 13:24
-
-
Save ok3141/eedfdcdb6297294ffa4269f712d7b3b5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Random; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.Executor; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.function.BiFunction; | |
import java.util.function.Function; | |
public class Main { | |
private static final Random random = new Random(); | |
public static void main(String[] args) throws InterruptedException { | |
ExecutorService executor = Executors.newSingleThreadExecutor(); | |
CommandExecutor commandExecutor = new CommandExecutorImpl(executor, Main::handleUrlSync); | |
for (int i = 0; i < 100; ++i) { | |
String url = "url" + (random.nextInt(10) + 1); | |
commandExecutor.requestAsync(url, Main::print); | |
Thread.sleep(random.nextInt(200)); | |
} | |
executor.shutdown(); | |
} | |
private static String handleUrlSync(String url) { | |
long start = System.currentTimeMillis(); | |
try { | |
Thread.sleep(random.nextInt(2000)); | |
} catch (InterruptedException ex) { | |
throw new RuntimeException(ex); | |
} | |
long end = System.currentTimeMillis(); | |
return start + " .. " + end; | |
} | |
private static Void print(String key, String value) { | |
System.out.println(key + " > " + value); | |
return null; | |
} | |
interface CommandExecutor { | |
void requestAsync(String url, BiFunction<String, String, Void> callback); | |
} | |
static class CommandExecutorImpl implements CommandExecutor { | |
private final Executor executor; | |
private final Function<String, String> urlHandler; | |
private final ConcurrentHashMap<String, List<BiFunction<String, String, Void>>> callbacks = new ConcurrentHashMap<>(); | |
public CommandExecutorImpl(Executor executor, Function<String, String> urlHandler) { | |
this.executor = executor; | |
this.urlHandler = urlHandler; | |
} | |
@Override | |
public void requestAsync(String url, BiFunction<String, String, Void> callback) { | |
List<BiFunction<String, String, Void>> list = callbacks.computeIfAbsent(url, $ -> new ArrayList<>()); | |
synchronized (list) { | |
list.add(callback); | |
if (list.size() == 1) { | |
executor.execute(() -> handleUrl(url, list)); | |
} | |
} | |
} | |
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") | |
private void handleUrl(String url, List<BiFunction<String, String, Void>> list) { | |
String response = urlHandler.apply(url); | |
if (callbacks.remove(url) != list) { | |
throw new IllegalStateException(); | |
} | |
synchronized (list) { | |
for (BiFunction<String, String, Void> callback : list) { | |
callback.apply(url, response); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment