import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class HtmlMaintenanceQueue {
private final BlockingQueue<String> taskQueue; // Queue for HTML document paths
private final RateLimiter rateLimiter; // Rate limiter for task execution
private final AtomicInteger taskCount = new AtomicInteger(0); //Counter for tasks
public HtmlMaintenanceQueue(int maxRequestsPerSecond) {
this.taskQueue = new LinkedBlockingQueue<>();
this.rateLimiter = new TokenBucketRateLimiter(maxRequestsPerSecond);
}
public synchronized void enqueueTask(String htmlDocumentPath) throws InterruptedException {
// Acquire a token from the rate limiter
rateLimiter.acquire();
// Add the task to the queue
taskQueue.offer(htmlDocumentPath);
System.out.println("Task enqueued: " + htmlDocumentPath);
}
public void processTasks() {
ExecutorService executor = Executors.newFixedThreadPool(1); //Single thread for processing
try {
while (true) {
String htmlDocumentPath = taskQueue.take(); // Get task from the queue
System.out.println("Processing task: " + htmlDocumentPath);
// Simulate maintenance task execution
try {
Thread.sleep(1000); // Simulate processing time
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Task completed: " + htmlDocumentPath);
}
} finally {
executor.shutdown();
}
}
public static void main(String[] args) throws InterruptedException {
int maxRequestsPerSecond = 5; //Limit the rate of requests
HtmlMaintenanceQueue queue = new HtmlMaintenanceQueue(maxRequestsPerSecond);
// Simulate enqueueing tasks
for (int i = 1; i <= 10; i++) {
queue.enqueueTask("html/" + i + ".html");
Thread.sleep(200); //Simulate task arrival rate
}
// Start processing tasks
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
queue.processTasks();
});
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
}
//Simple Token Bucket implementation
static class TokenBucketRateLimiter {
private final int capacity;
private final long refillRate;
private long tokens;
private final ScheduledExecutorService refiller;
public TokenBucketRateLimiter(int capacity) {
this.capacity = capacity;
this.tokens = capacity;
this.refiller = Executors.newScheduledThreadPool(1);
refiller.scheduleAtFixedRate(this::refill, 0, 1000, TimeUnit.MILLISECONDS); //Refill every 1 second
}
public synchronized void acquire() throws InterruptedException {
while (tokens <= 0) {
wait(); //Wait until a token is available
}
tokens--;
}
private void refill() {
synchronized (this) {
tokens = Math.min(capacity, tokens + (capacity / 1000)); //Refill at capacity/refillRate
}
}
}
}
Add your comment