Reputation: 971
I know that run method should not be called to start a new thread execution, but i was referring this article where they have called runnable.run();
inside another run method and it seems to be implying that it starts a new thread or its not at all creating threads, it just creates a new thread and runs all runnable in the same thread i.e task by task?
here is the code that article refers about.
public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks){
taskQueue = new BlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++){
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads){
thread.start();
}
}
public synchronized void execute(Runnable task) throws Exception{
if(this.isStopped) throw
new IllegalStateException("ThreadPool is stopped");
this.taskQueue.enqueue(task);
}
public synchronized void stop(){
this.isStopped = true;
for(PoolThread thread : threads){
thread.doStop();
}
}
}
and
public class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue){
taskQueue = queue;
}
public void run(){
while(!isStopped()){
try{
Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();
} catch(Exception e){
//log or otherwise report exception,
//but keep pool thread alive.
}
}
}
public synchronized void doStop(){
isStopped = true;
this.interrupt(); //break pool thread out of dequeue() call.
}
public synchronized boolean isStopped(){
return isStopped;
}
}
questions:
Why thread.start(); is called inside constructor?
How do i enque my task if thread.start(); is called even before calling this.taskQueue.enqueue(task);
To understand all these please post a driver class for this example with maxNoOfTasks=10 and noOfThreads=3.and output for the same would be much appreciated.
thanks
Upvotes: 6
Views: 1161
Reputation: 573
4. Does Runnable.run() inside run method start a new thread ?
No, it will not start a new thread, It is not possible to start a new thread by calling run() method because JVM will not create a new thread until you call the start method.
If you call the run() method directly than it will be called on the same thread. JVM will not create separate thread for execution, it will execute on same thread.
On any thread instance if you call start() method it will create a new thread but if you call start() method second time on same instance, it will throw java.lang.IllegalStateException, because the thread is already started and you cannot restart it again.
You can only pause a thread in Java. Once it died it's gone.
I think this could be the reason to call like this.
Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();
Upvotes: 3
Reputation: 1074268
i was referring this article where they have called
runnable.run()
; inside another run method and it seems to be implying that it starts a new thread.
Looking at the code, I don't see that implication at all.
It's not starting a new thread. It's running the next Runnable
from a queue on the current pool thread.
I know that run method should not be called to start a new thread execution...
Not should not, cannot. :-) Calling run
just calls run
, on the current thread, just like any other method call.
- Why
thread.start();
is called inside constructor?
To start the thread that was just created with new PoolThread(taskQueue)
.
- How do i enque my task if
thread.start();
is called even before callingthis.taskQueue.enqueue(task);
You pass it into execute
. It gets added to the queue of things to do (taskQueue
). One of the PoolThread
s that ThreadPool
created will pick it up when it's next free.
- To understand all these please post a driver class for this example with maxNoOfTasks=10 and noOfThreads=3.and output for the same would be much appreciated.
I don't know what you mean by a driver class, but I think answering the questions is sufficient.
- Does
Runnable.run()
inside run method start a new thread ?
No.
So to understand what this does, say you create a ThreadPool
with 5 threads. The ThreadPool
constructor creates and starts five PoolThread
threads immediately. Those threads constantly check taskQueue
to see if there's anything to do and, if so, they do it.
Initially, of course, taskQueue
is always empty so the threads are busy-waiting, constantly spinning checking for something in taskQueue
. (This isn't really ideal, it burns CPU for no good reason. It would be better to suspend threads when there's nothing to do, but that's starting to get pretty far from the actual question.)
Then, at some point, you call execute
and pass in a task. That adds it to the taskQueue
. The next time one of the five threads checks for something in taskQueue
, it finds it, and runs it on that thread (not a new one).
Upvotes: 10
Reputation: 1010
Why thread.start(); is called inside constructor?
starts the threads in pool constructor.
the threads are already running.
Runnable runnable = (Runnable) taskQueue.dequeue();
blocks the running threads
taskQueue.enque() puts new object of type Runnable to the queue and any blocked thread takes this Runnable and executes it. All the threads are started when the pool is created and in those threads are Runnable simply executed.
Upvotes: 2