Reputation: 79
I was trying to understand for custom thread pool implementation as explained in https://www.roytuts.com/custom-thread-pool-in-java/. After polling out of task queue as
while ((r = taskQueue.poll()) != null) {
r.run();
}
the code is directly calling run method without calling start()
first. So, i am bit confused how runnable can be started without creating thread on runnable and then call start method? Can anyone please clear out my confusion where i am lacking the understanding. Thanks
class CustomThreadPool {
// holds tasks
private BlockingQueue<Runnable> runnableQueue;
// holds the pool of worker threads
//private List<WorkerThread> threads;
// check if shutdown is initiated
private AtomicBoolean isThreadPoolShutDownInitiated;
public CustomThreadPool(final int noOfThreads) {
this.runnableQueue = new LinkedBlockingQueue<>();
//this.threads = new ArrayList<>(noOfThreads);
this.isThreadPoolShutDownInitiated = new AtomicBoolean(false);
// create worker threads
for (int i = 1; i <= noOfThreads; i++) {
WorkerThread thread = new WorkerThread(runnableQueue, this);
thread.setName("Worker Thread - " + i);
thread.start();
// threads.add(thread);
}
}
public void execute(Runnable r) throws InterruptedException {
if (!isThreadPoolShutDownInitiated.get()) {
runnableQueue.put(r);
} else {
throw new InterruptedException("Thread Pool shutdown is initiated, unable to execute task");
}
}
public void shutdown() {
isThreadPoolShutDownInitiated = new AtomicBoolean(true);
}
private class WorkerThread extends Thread {
// holds tasks
private BlockingQueue<Runnable> taskQueue;
// check if shutdown is initiated
private CustomThreadPool threadPool;
public WorkerThread(BlockingQueue<Runnable> taskQueue, CustomThreadPool threadPool) {
this.taskQueue = taskQueue;
this.threadPool = threadPool;
}
@Override
public void run() {
try {
// continue until all tasks finished processing
while (!threadPool.isThreadPoolShutDownInitiated.get() || !taskQueue.isEmpty()) {
Runnable r;
// Poll a runnable from the queue and execute it
while ((r = taskQueue.poll()) != null) {
r.run();
}
Thread.sleep(1);
}
} catch (RuntimeException | InterruptedException e) {
throw new CustomThreadPoolException(e);
}
}
}
private class CustomThreadPoolException extends RuntimeException {
private static final long serialVersionUID = 1L;
public CustomThreadPoolException(Throwable t) {
super(t);
}
}
}
public class ThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
Runnable r = () -> {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " is executing task.");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
CustomThreadPool threadPool = new CustomThreadPool(2);
threadPool.execute(r);
threadPool.execute(r);
threadPool.shutdown();
// threadPool.execute(r);
}
}
Upvotes: 1
Views: 470
Reputation: 3226
Your thread pool class calls thread.start()
which calls runnable.run()
by calling thread.run()
. The last method is designed for threads initialized with runnable and can be called directly or via start()
.
According to Oracle docs: start()
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
EDIT
Calling runnable.run()
method simply synchronously executes runnable on the current thread (in which the method was called). In your case it is separate ones (which are created in CustomThreadPool). You can call run()
directly in main()
, which will synchronously execute the runnable on the main thread. Generally, the example is not breaking any concepts of using runnables, since it executes them on separate threads.
To make a long story short: asynchronous behavior is achieved by executing runnables on different threads. In scope of a single thread, calling multiple runnables' run()
will execute them synchronously one by one.
Upvotes: 1