I was asked to write a java method executeInParallel that executes without active waiting and without race conditions(so i thought that i needed an ArrayBlockingQueue).I was also asked to not use other classes than the ones already in my code
import java.util.concurrent.ArrayBlockingQueue;
public class ParallelExecutor {
public static void executeInParallel(Runnable[] runnables, int K) {
if (K <= 0)
throw new IllegalArgumentException("Can't execute zero or less concurrent runnables");
if (runnables == null || runnables.length == 0)
throw new IllegalArgumentException("Must provide something to run");
ArrayBlockingQueue<Runnable> taskQueue = new ArrayBlockingQueue<>(K); // Extra space for end markers
// Start the producer
Thread producer = new Thread(() -> {
try {
for (Runnable r : runnables) {
taskQueue.put(r); // Put a runnable in the queue
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
// Start the consumer threads
K=Math.min(runnables.length,K);
Thread[] consumers = new Thread[K];
for (int i = 0; i < K; i++) {
consumers[i] = new Thread(() -> {
try {
Runnable r;
while((r= taskQueue.take())!=null){
r.run();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
e.printStackTrace(); // Handle exceptions as needed
}
});
consumers[i].start();
}
// Wait for the producer to finish
try {
producer.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// Wait for all consumers to finish
for (Thread consumer : consumers) {
try {
consumer.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
// Example usage
Runnable[] tasks = new Runnable[20];
for (int i = 0; i < tasks.length; i++) {
final int index = i;
tasks[i] = () -> {
System.out.println("Task " + index + " is running.");
try {
Thread.sleep(1000); // Simulate work that takes 1 second
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Task " + index + " is finished.");
};
}
executeInParallel(tasks, 3); // Execute tasks in parallel, 3 at a time
}
}
and the code loops in this part after all the r.run are executed:
while((r= taskQueue.take())!=null){
r.run();
}
How i can remove the loop without adding active wait(i need passive waiting and i was asked to not add other classes like ExecutorService etc.)?
I tried removing the while with something else but i was asked to have k run in parallel so i cant do it without more threads i think
The taskQueue.take()
may wait forever until the new task put in the taskQueue ,here is the source code:
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
// continue waiting
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
so consider using taskQueue.poll(0,TimeUnit.SECONDS)
, so it could immediately return task or null.