amarnath harish
amarnath harish

Reputation: 971

is it possible to start a thread by calling run() inside a run()method?

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:

  1. Why thread.start(); is called inside constructor?

  2. How do i enque my task if thread.start(); is called even before calling this.taskQueue.enqueue(task);

  3. 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.

  4. Does Runnable.run() inside run method start a new thread ?

thanks

Upvotes: 6

Views: 1161

Answers (3)

sagar varsani
sagar varsani

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

T.J. Crowder
T.J. Crowder

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.

  1. Why thread.start(); is called inside constructor?

To start the thread that was just created with new PoolThread(taskQueue).

  1. How do i enque my task if thread.start(); is called even before calling this.taskQueue.enqueue(task);

You pass it into execute. It gets added to the queue of things to do (taskQueue). One of the PoolThreads that ThreadPool created will pick it up when it's next free.

  1. 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.

  1. 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

Michal
Michal

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

Related Questions