newFixedThreadPool的内部工作

时间:2015-06-29 19:01:15

标签: java multithreading concurrency

请帮助我理解newFixedThreadPool(或Cached)的内部流程

当我们写下面的陈述时, ExecutorService e = Executors.newFixedThreadPool(3);

  1. e.execute(runaable1);
  2. e.execute(runaable2);
  3. e.execute(runaable3);
  4. e.execute(runaable4);
  5. e.execute(runaable5);
  6. 直到3个执行方法,将创建三个线程,当调用第四个执行方法时,不会创建新线程,但工作将等待线程空闲。

    我不明白这一点“不会创建新的线程,但工作将等待线程自由。”我认为当runnable1将被赋予第一个创建的线程时,一旦runnable1的run方法完成,Thread1的运行也将完成,thread1将无法调用runnable4的run方法。 那么,java如何通过3个线程来管理执行5 Runnable。

2 个答案:

答案 0 :(得分:4)

仅供参考:这是一个非常简单的线程池实现。

class MyThreadPool implements java.util.concurrent.Executor 
{
    private final java.util.concurrent.BlockingQueue<Runnable> queue;

    public MyThreadPool(int numThreads) {
        queue = new java.util.concurrent.LinkedBlockingQueue<>();
        for (int i=0 ; i<numThreads ; i++) {
            new Thread(new Runnable(){
                @Override
                public void run() {
                    while(true) {
                        queue.take().run();
                    }
                }
            }).start();
        }
    }

    @Override
    public void execute(Runnable command) {
        queue.put(command);
    }
}

这不会编译,因为我没有处理InterruptedException,并且在真正的线程池中,您还希望处理给定{{1}可能抛出的异常但它应该让你大致了解线程池的作用。

它创建一个队列和任意数量的工作线程。工作线程彼此竞争以从队列中使用命令。队列是command,所以当队列为空时,工作人员都会休眠。

其他线程可能会生成新命令(即BlockingQueue个对象),并调用Runnable方法将新命令放入队列中。这些命令将由工作线程执行(即,它们的运行方法将被调用),其顺序与它们排队的顺序大致相同。

  • 大概是因为工作人员A可以从队列中选择一个新命令,然后在调用命令的execute(command)方法之前丢失其时间片。然后,其他工作人员可以从队列中选择其他命令并在调度程序允许工作人员A再次运行之前执行它们。

答案 1 :(得分:2)

执行ExecutorService e=Executors.newFixedThreadPool(3);时,将创建一个包含3个线程的线程池。这3个线程将用于执行在e对象上执行的任何任务。

当你尝试通过ExecutorService执行任务时,它会被添加到任务队列中,如果池中的线程数大于任务数,那么一旦某个任务到来,就会有一些免费线程在池中将被选中并用于执行任务。

当任务数量大于池中的线程数时,它们将被添加到队列中的pipleline中,并且一旦某个线程完成执行,该线程将用于从队列管道执行任务。

线程池:
刚刚完成的线程不会终止。请注意,它是一个线程池,因此线程被池化,这意味着它们不会终止(通常,直到你有一些超时或其他机制),但会返回池中,以便它们可以重用。这就是你的第4和第5个runnable将通过这些汇集线程执行的原因。

  

&#34;不会创建新线程,但工作将等待线程   是免费的。&#34;

这与上面讨论的相同,然后他们在队列中等待,并且一旦某个线程完成任务执行,队列中的等待任务将被合并并从自由线程执行,这将清除队列中的所有任务。

由于您使用了newFixedThreadPool,因此不会创建新的线程,因此会创建一个包含3个线程的固定线程池,它们将仅用于处理请求到{{1}的特定实例的所有请求在你的情况下,它是ExecutorService

其他线程池选项:
您可以使用e以多种方式创建线程池。例如,使用java.util.concurrent.Executors,您可以创建一个根据需要创建新线程的线程池,但在它们可用时将重用先前构造的线程。
检查所有可能的方法,找到最适合您的方式。