【问题标题】:is it possible to start a thread by calling run() inside a run()method?是否可以通过在 run() 方法中调用 run() 来启动线程?
【发布时间】:2018-05-29 11:05:41
【问题描述】:

我知道不应调用 run 方法来启动新线程执行,但我指的是this article,他们在另一个 run 方法中调用了runnable.run();,这似乎暗示它启动了一个新线程或它根本没有创建线程,它只是创建一个新线程并在同一个线程中运行所有可运行的,即逐个任务?

这里是文章提到的代码。

 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=10noOfThreads=3。输出 同样将不胜感激。

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

谢谢

【问题讨论】:

  • run 方法只是一个普通的方法,没什么特别的。 Thread#start 方法启动一个线程。之后它调用run。但是run本身只执行方法,与线程无关。 Runnable 不是线程,它只是有一个名为 run 的方法。

标签: java multithreading


【解决方案1】:

我指的是这篇文章,他们称之为runnable.run();在另一个 run 方法中,它似乎暗示它启动了一个新线程。

查看代码,我完全没有看到这种含义。

它不是开始一个新线程。它正在当前池线程上的队列中运行下一个Runnable

我知道不应该调用run方法来开始一个新的线程执行...

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

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

启动刚刚使用new PoolThread(taskQueue) 创建的线程。

  1. 如果在调用this.taskQueue.enqueue(task); 之前调用了thread.start();,我如何查询我的任务

你将它传递给execute。它被添加到待办事项队列中 (taskQueue)。 ThreadPool 创建的 PoolThreads 之一将在下一次空闲时将其拾取。

  1. 要了解所有这些,请为此示例发布一个驱动程序类,其中 maxNoOfTasks=10 和 noOfThreads=3。非常感谢您提供相同的输出。

我不知道您所说的驱动程序类是什么意思,但我认为回答问题就足够了。

  1. Runnable.run() inside run 方法是否启动一个新线程?

没有。


所以要理解它的作用,假设你创建了一个有 5 个线程的ThreadPoolThreadPool 构造函数立即创建并启动五个PoolThread 线程。这些线程不断检查taskQueue 以查看是否有任何事情要做,如果有,他们就会去做。

当然,最初taskQueue 总是空的,所以线程忙于等待,不断地旋转检查taskQueue 中的某些内容。 (这不是很理想,它会无缘无故地消耗 CPU。最好在无事可做时暂停线程,但这与实际问题相差甚远。)

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

【讨论】:

  • 请您发布一个驱动程序类,它可以产生一些输出以更好地理解这一点?
  • 你可以解释一下OP似乎不熟悉的线程池的概念。
【解决方案2】:

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

不,它不会启动一个新线程,调用run()方法是不可能启动一个新线程的,因为JVM不会在你调用start方法之前创建一个新线程。

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

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

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

我认为这可能是这样打电话的原因。

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

【讨论】:

    【解决方案3】:

    为什么是 thread.start();在构造函数内部调用?

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

    线程已经在运行。

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

    阻塞正在运行的线程

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      • 2014-12-25
      • 2022-10-25
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 2016-01-07
      相关资源
      最近更新 更多