I read that ThreadPoolExecutor
has pool of threads and this pool is destined to reduce cost of creation new threads (at least I understood phrase below in such way):
When you send a task to the executor, it tries to use a pooled thread for the execution of this task, to avoid continious spawning of threads. [Java 7 Concurrency Cookbook]
BUT, as I know we have got no way to restart thread in Java.
Question: How does ThreadPoolExecutor avoid creation of new threads?
Heterogeneous tasks, not homogeneous tasks. Reuse threads, not single use. Manage multiple tasks, not single tasks.
One way to do your own thread pool is to use a blocking queue on to which you enqueue runnables and have each of your thread, once it's done processing the run() method of a Runnable , dequeue the next Runnable (or block) and run its run() method, then rinse and repeat.
The technique of thread pooling allows threads to be reused to reduce thread creation overhead or when creating an unbounded number of threads can diminish the reliability of the system.
Instead of creating new threads when new tasks arrive, a thread pool keeps a number of idle threads that are ready for executing tasks as needed. After a thread completes execution of a task, it does not die. Instead it remains idle in the pool waiting to be chosen for executing new tasks.
It's very simple - in essence the Thread
s sleep, waiting to be woken by a task - they run that task and then sleep again.
public static void main(final String[] args) throws Exception {
final BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<>();
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
blockingQueue.take().run();
} catch (InterruptedException ex) {
return;
}
}
}
});
t.start();
blockingQueue.add(new Runnable() {
@Override
public void run() {
System.out.println("Task 1");
}
});
blockingQueue.add(new Runnable() {
@Override
public void run() {
System.out.println("Task 2");
}
});
}
The BlockingQueue
will block a Thread
while it is empty. When I add an item, and Thread
(s) currently blocked are awoken and one will take the task (LinkedBlockingDeque
is thread safe). When the Thread
is done with the task it goes back to sleep.
The JavaDoc for ThreadPoolExecutor
describes the logic in detail. All of the constructors for ThreadPoolExecutor
take a BlockingQueue<Runnable>
- this should give you a hint as so how the logic works.
NB: This is not the same as busy waiting. A BlockingQueue
uses wait
and notify
to suspend and wake Thread
s, this means that the Thread
s in the pool are not doing any work when they are not processing tasks. A busy wait based approach would not work because the Thread
s would block up all the CPU cores with their polling not allowing the program to proceed (or at least severely impairing it).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With