newFixedThreadPool的内部工作
请帮助我理解newFixedThreadPool(或Cached)的内部流程
当我们写下面的语句时,ExecutorService e = Executors.newFixedThreadPool(3);
- e.execute(runaable1);
- e.execute(runaable2);
- e.execute(runaable3);
- e.execute(runaable4);
- e.execute(runaable5);
直到3个执行方法,将创建三个线程,当调用第四个执行方法时,不会创建新线程,但工作将等待线程空闲。
我不明白这一点“不会创建新的线程,但工作将等待线程自由。” 我认为当runnable1将被赋予第一个创建的线程时,一旦runnable1的run方法完成,Thread1的运行也将完成,thread1将无法调用runnable4的run方法。 那么,java如何通过3个线程来管理执行5 Runnable。
仅供参考:这是一个非常简单的线程池实现。
class MyThreadPool implements java.util.concurrent.Executor { private final java.util.concurrent.BlockingQueue queue; public MyThreadPool(int numThreads) { queue = new java.util.concurrent.LinkedBlockingQueue<>(); for (int i=0 ; i
这不会编译,因为我没有处理InterruptedException,并且在一个真正的线程池中,你也想要处理给定command
可能抛出的exception,但它应该让你大致了解一个线程是什么游泳池。
它创建一个队列和任意数量的工作线程 。 工作线程彼此竞争以消耗队列中的命令 。 队列是一个BlockingQueue
,所以当队列为空时,工作人员都会hibernate。
其他线程可能会生成新命令(即Runnable
对象),并调用execute(command)
方法将新命令放入队列中。 这些命令将由工作线程以与它们排队的大致相同的顺序执行(即,它们的运行方法将被调用)。
- 大概是因为工作者A可以从队列中选择一个新命令,然后在调用命令的
.run()
方法之前丢失其时间片。 然后,其他工作人员可以从队列中选择其他命令并在调度程序允许工作人员A再次运行之前执行它们。
执行ExecutorService e=Executors.newFixedThreadPool(3);
将创建一个包含3个线程的线程池。 这三个线程将用于执行在您对象上执行的任何任务。
当您尝试通过ExecutorService
执行任务时,它将被添加到任务队列中,如果池中的线程数大于任务数,那么一旦某个任务到来,池中的一些空闲线程将被选中并且用来执行任务。
当任务数量大于池中的线程数时,它们将被添加到队列中的pipleline中,并且一旦某个线程完成执行,该线程将用于从队列管道执行任务。
线程池:
刚刚完成的线程不会终止。 请注意,它是一个线程池,因此线程被池化,这意味着它们不会终止(通常,直到你有一些超时或其他机制),但会返回池中,以便它们可以重用。 这就是你的第4和第5个runnable将通过那些池化线程执行的原因。
“将不会创建新的线程,但工作将等待线程自由。”
这与上面讨论的相同,然后他们在队列中等待,并且一旦某个线程完成任务执行,队列中的等待任务将被合并并从自由线程执行,这将发生直到清除队列中的所有任务。
由于您使用了newFixedThreadPool
,因此不会创建新的线程,因此创建了3个线程的固定线程池,它们将仅用于处理请求到ExecutorService
特定实例的所有任务,在您的情况下,它是e
。
其他线程池选项:
您可以使用java.util.concurrent.Executors
以多种方式创建线程池。 例如,使用Executors#newCachedThreadPool()
您可以创建一个根据需要创建新线程的线程池,但在它们可用时将重用以前构造的线程。
检查所有可用的方法,找到最适合您的方法。