1. import java.net.MalformedURLException;
  2. import java.net.URL;
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import java.util.concurrent.ConcurrentLinkedQueue;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7. import java.util.concurrent.TimeUnit;
  8. public class RequestThrottler {
  9. private final int maxRequestsPerSecond;
  10. private final int timeoutMillis;
  11. private final ConcurrentHashMap<URL, Long> lastRequestTimes = new ConcurrentHashMap<>();
  12. private final ConcurrentLinkedQueue<URL> queue = new ConcurrentLinkedQueue<>();
  13. private final ExecutorService executor = Executors.newFixedThreadPool(5); // Adjust thread pool size as needed
  14. public RequestThrottler(int maxRequestsPerSecond, int timeoutMillis) {
  15. this.maxRequestsPerSecond = maxRequestsPerSecond;
  16. this.timeoutMillis = timeoutMillis;
  17. }
  18. public void enqueueRequest(URL url) {
  19. queue.offer(url);
  20. processQueue();
  21. }
  22. private void processQueue() {
  23. while (!queue.isEmpty()) {
  24. URL url = queue.poll();
  25. if (isAllowedToRequest(url)) {
  26. executor.submit(fetchHtmlPage, url);
  27. } else {
  28. // Request throttled, re-enqueue after waiting
  29. long waitTime = calculateWaitTime(url);
  30. try {
  31. TimeUnit.MILLISECONDS.sleep(waitTime);
  32. } catch (InterruptedException e) {
  33. Thread.currentThread().interrupt();
  34. }
  35. queue.offer(url);
  36. }
  37. }
  38. }
  39. private boolean isAllowedToRequest(URL url) {
  40. long lastRequestTime = lastRequestTimes.getOrDefault(url, 0L);
  41. long currentTime = System.currentTimeMillis();
  42. if (currentTime - lastRequestTime < timeoutMillis) {
  43. return false; // Request throttled
  44. }
  45. lastRequestTimes.put(url, currentTime);
  46. return true; // Request allowed
  47. }
  48. private long calculateWaitTime(URL url) {
  49. long lastRequestTime = lastRequestTimes.getOrDefault(url, 0L);
  50. long currentTime = System.currentTimeMillis();
  51. long timeSinceLastRequest = currentTime - lastRequestTime;
  52. return (1000 / maxRequestsPerSecond) * (maxRequestsPerSecond - (int) (timeSinceLastRequest / (1000.0/maxRequestsPerSecond)));
  53. }
  54. private Runnable fetchHtmlPage(URL url) {
  55. return () -> {
  56. try {
  57. // Simulate fetching the HTML page
  58. System.out.println("Fetching: " + url.toURI());
  59. TimeUnit.SECONDS.sleep(2); // Simulate network latency
  60. System.out.println("Fetched: " + url.toURI());
  61. } catch (InterruptedException e) {
  62. Thread.currentThread().interrupt();
  63. }
  64. };
  65. }
  66. public void shutdown() {
  67. executor.shutdown();
  68. try {
  69. executor.awaitTermination(5, TimeUnit.SECONDS);
  70. } catch (InterruptedException e) {
  71. Thread.currentThread().interrupt();
  72. }
  73. }
  74. public static void main(String[] args) throws MalformedURLException {
  75. RequestThrottler throttler = new RequestThrottler(2, 1000); // Allow 2 requests per second, 1 second timeout
  76. URL url1 = new URL("https://www.example.com");
  77. URL url2 = new URL("https://www.google.com");
  78. URL url3 = new URL("https://www.example.com"); // Same as url1
  79. throttler.enqueueRequest(url1);
  80. throttler.enqueueRequest(url2);
  81. throttler.enqueueRequest(url3);
  82. throttler.enqueueRequest(new URL("https://www.yahoo.com"));
  83. throttler.enqueueRequest(new URL("https://www.bing.com"));
  84. throttler.shutdown();
  85. }
  86. }

Add your comment