是否可以通过在run()方法中调用run()来启动一个线程?

时间:2018-05-29 11:05:41

标签: java multithreading

我知道不应该调用run方法来启动新的线程执行,但是我引用了this article,他们在另一个run方法中调用了runnable.run();,这似乎意味着它开始了一个新线程或者它根本不是 创建 线程,它只是创建一个新线程并在同一个线程中运行所有runnable,即按任务执行任务?

这是文章引用的代码。

 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();
        }
    }

}

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;
    }
}

的问题:

  1. 为什么在构造函数中调用 thread.start();

  2. 如果在之前调用 thread.start(); ,我该如何识别我的任务 调用 this.taskQueue.enqueue(task);

  3. 要了解所有这些,请为此示例发布一个驱动程序类 maxNoOfTasks = 10 noOfThreads = 3 。输出         我将非常感激。

  4. run方法中的Runnable.run()是否会启动一个新线程?
  5. 感谢

3 个答案:

答案 0 :(得分:10)

  

我在引用这篇文章的时候称他们为runnable.run();在另一个run方法中,它似乎意味着它启动了一个新线程。

看一下代码,我根本没有看到这个含义。

它没有开始新线程。它从当前池线程的队列中运行下一个Runnable

  

我知道不应该调用run方法来启动新的线程执行...

不应该不能。 :-)在当前线程上调用run只调用run,就像任何其他方法调用一样。

  
      
  1. 为什么在构造函数中调用thread.start();
  2.   

启动刚刚使用new PoolThread(taskQueue)创建的主题。

  
      
  1. 如果在调用thread.start();
  2. 之前调用this.taskQueue.enqueue(task);,我该如何处理我的任务?   

您将其传递给execute。它被添加到要做的事情的队列中(taskQueue)。 PoolThread创建的ThreadPool之一会在下一次免费时将其提取。

  
      
  1. 要理解所有这些,请为此示例发布一个驱动程序类,其中包含maxNoOfTasks = 10和noOfThreads = 3.并且非常感谢输出。
  2.   

我不知道司机班的意思,但我认为回答问题就足够了。

  
      
  1. 运行方法中的Runnable.run()是否会启动一个新线程?
  2.   

没有

所以要了解它的作用,请说你创建一个包含5个线程的ThreadPoolThreadPool构造函数立即创建并启动五个PoolThread个线程。那些线程经常检查taskQueue以查看是否有任何事情要做,如果有,他们会这样做。

当然,最初,taskQueue始终为空,因此线程正忙着等待,不断地在taskQueue中检查某些内容。 (这不是非常理想的,它没有任何理由燃烧CPU。最好在没有任何事情的情况下暂停线程,但这已经开始远离实际的问题了。)

然后,在某些时候,您调用execute并传递任务。这会将其添加到taskQueue。下一次五个线程中的一个检查taskQueue中的某个内容时,它会找到它,然后在该线程上运行 (而不是新线程)。

答案 1 :(得分:3)

<强> 4。 Run方法中的Runnable.run()是否会启动一个新线程?

不,它不会启动新线程,不能通过调用run()方法启动新线程,因为在调用start方法之前JVM不会创建新线程。

如果直接调用run()方法,则会在同一个线程上调用它。 JVM不会创建单独的线程来执行,它将在同一个线程上执行。

在任何线程实例上,如果你调用start()方法,它将创建一个新线程,但是如果你在同一个实例上第二次调用start()方法,它将抛出java.lang.IllegalStateException,因为该线程已经启动并且你不能再重新启动它。

您只能在Java中暂停一个线程。一旦它死了它就消失了。

我认为这可能是这样打电话的理由。

Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();

答案 2 :(得分:2)

  

为什么要thread.start();在构造函数中调用?

启动池构造函数中的线程。

线程已经在运行。

Runnable runnable = (Runnable) taskQueue.dequeue();

阻止正在运行的线程

taskQueue.enque()将类型为Runnable的新对象放入队列,任何被阻塞的线程都会获取此Runnable并执行它。创建池时会启动所有线程,并且这些线程只是简单执行Runnable。