Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 978
amarnath harish Avatar asked May 29 '18 11:05

amarnath harish


People also ask

Is it possible to call a run () method of a thread class?

The run() method is available in the thread class constructed using a separate Runnable object. Otherwise, this method does nothing and returns. We can call the run() method multiple times.

Is it possible to call run () method instead of start () on a thread in Java?

No, you can not directly call run method to start a thread. You need to call start method to create a new thread. If you call run method directly , it won't create a new thread and it will be in same stack as main.

Can we call run method directly to start a thread?

But if we directly call the run() method then no new thread will be created and run() method will be executed as a normal method call on the current calling thread itself and no multi-threading will take place.

What happens when you call run () instead of start () on thread?

If run() method is called directly instead of start() method in Java code, run() method will be treated as a normal overridden method of the thread class (or runnable interface). This run method will be executed within the context of the current thread, not in a new thread.


1 Answers

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

like image 80
T.J. Crowder Avatar answered Sep 28 '22 16:09

T.J. Crowder