ExecutorService(int n) 和 Thread.activeCount() 是如何工作的?
How does the ExecutorService(int n) and Thread.activeCount() work?
我有以下代码片段:
int k = 4;
ExecutorService e = Executors.newFixedThreadPool(k);
for (int i = 1; i <= k; i++) {
e.execute(new C(i));
e.execute(new C(i));
}
int active = Thread.activeCount();
System.out.println(active);
e.shutdown();
清晰可见我通过循环每次迭代提交两个 C
。在我的例子中,提交了 8 C
,即使 ExecutorService 的大小固定为 4。
这也可以通过计算活动线程 5 来确认。
这种行为是故意的吗?我不明白为什么似乎只有 4 个新线程被启动和计数,尽管提交了 8 个。如果有人能为我澄清 ExecutorService 和 Thread.activeCount() 的概念,我会很高兴。
您创建的 ExecutorService 的主要目标是一个 fixed-size 线程池(在您的例子中是四个线程)。如果您只看到为您的八项工作创建了四个 Thread 实例,那么它正在按设计工作。
您似乎认为应该创建八个线程。想象一下,如果您提交了 100 万件作品;如果创建一百万个线程,那将是一场灾难。
抽象允许您控制一次使用多少线程,而不考虑有多少项目要处理。 ExecutorService 处理根据需要多次重用四个线程的复杂性,以处理您传递给调用 execute
.
的所有项目
可以用银行来类比。您创建了一家银行,其中有四个出纳员(线程池中的四个线程)和八个客户(对 execute
的八次调用)。当出纳员完成与客户的交易后,排队的下一位客户将由该出纳员提供服务。您通过调用 execute
将某人添加到队列中,ExecutorService 管理其他一切。您可以通过初始化 ExecutorService 的方式来控制线程(出纳员)的数量(您可以创建许多不同的风格)。
I don't understand why seemingly just 4 new threads are started and counted, eventhough 8 are submitted.
不要混淆线程和任务。您已经为 4 个线程创建了一个固定的 ThreadPool,池中将只保留 4 个线程。
检查 Executors
的实现
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* <tt>nThreads</tt> threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if <tt>nThreads <= 0</tt>
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
您可以在官方文档页面找到有关 ThreadPoolExecutor 各个参数的更多详细信息。
在你的例子中,线程数是 4。工作任务(实现 Runnable 接口)的数量是 8。
How are they stored, how can they be accessed? Is it also possible to manipulate them midway, maybe why other calls arrive?
- 任务已提交到任务队列(
BlockingQueue
)
- 如果
BlockingQueue
已满(有界队列),将触发拒绝策略。
- 如果 BlockingQueue 未满,工作任务将等待 Thread pick-up 它们。
相关 SE 帖子:
我有以下代码片段:
int k = 4;
ExecutorService e = Executors.newFixedThreadPool(k);
for (int i = 1; i <= k; i++) {
e.execute(new C(i));
e.execute(new C(i));
}
int active = Thread.activeCount();
System.out.println(active);
e.shutdown();
清晰可见我通过循环每次迭代提交两个 C
。在我的例子中,提交了 8 C
,即使 ExecutorService 的大小固定为 4。
这也可以通过计算活动线程 5 来确认。
这种行为是故意的吗?我不明白为什么似乎只有 4 个新线程被启动和计数,尽管提交了 8 个。如果有人能为我澄清 ExecutorService 和 Thread.activeCount() 的概念,我会很高兴。
您创建的 ExecutorService 的主要目标是一个 fixed-size 线程池(在您的例子中是四个线程)。如果您只看到为您的八项工作创建了四个 Thread 实例,那么它正在按设计工作。
您似乎认为应该创建八个线程。想象一下,如果您提交了 100 万件作品;如果创建一百万个线程,那将是一场灾难。
抽象允许您控制一次使用多少线程,而不考虑有多少项目要处理。 ExecutorService 处理根据需要多次重用四个线程的复杂性,以处理您传递给调用 execute
.
可以用银行来类比。您创建了一家银行,其中有四个出纳员(线程池中的四个线程)和八个客户(对 execute
的八次调用)。当出纳员完成与客户的交易后,排队的下一位客户将由该出纳员提供服务。您通过调用 execute
将某人添加到队列中,ExecutorService 管理其他一切。您可以通过初始化 ExecutorService 的方式来控制线程(出纳员)的数量(您可以创建许多不同的风格)。
I don't understand why seemingly just 4 new threads are started and counted, eventhough 8 are submitted.
不要混淆线程和任务。您已经为 4 个线程创建了一个固定的 ThreadPool,池中将只保留 4 个线程。
检查 Executors
的实现 /**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* <tt>nThreads</tt> threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if <tt>nThreads <= 0</tt>
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
您可以在官方文档页面找到有关 ThreadPoolExecutor 各个参数的更多详细信息。
在你的例子中,线程数是 4。工作任务(实现 Runnable 接口)的数量是 8。
How are they stored, how can they be accessed? Is it also possible to manipulate them midway, maybe why other calls arrive?
- 任务已提交到任务队列(
BlockingQueue
) - 如果
BlockingQueue
已满(有界队列),将触发拒绝策略。 - 如果 BlockingQueue 未满,工作任务将等待 Thread pick-up 它们。
相关 SE 帖子: