ThreadPoolExecutor中largestPoolSize和maximumPoolSize的区别
时间: 2023-11-02 07:36:41 浏览: 190
`largestPoolSize` 和 `maximumPoolSize` 都是 ThreadPoolExecutor 中的属性,但是它们的含义略有不同。
`largestPoolSize` 表示线程池曾经达到过的最大线程数量,它记录的是线程池在运行过程中出现的最大线程数,即使线程池中的线程已经被回收了,该值也不会减小。可以通过调用 ThreadPoolExecutor 的 `getLargestPoolSize()` 方法来获取当前的 largestPoolSize 值。
`maximumPoolSize` 表示线程池中允许的最大线程数量,它是在创建线程池时指定的参数。当线程池中的线程数达到这个值时,新的任务将被阻塞,直到线程池中有线程空闲出来可以处理新的任务。可以通过调用 ThreadPoolExecutor 的 `getMaximumPoolSize()` 方法来获取当前的 maximumPoolSize 值。
因此,可以说 `largestPoolSize` 是记录线程池历史运行状态的属性,而 `maximumPoolSize` 是限制线程池最大线程数的属性。
相关问题
java中多线程框架
### Java多线程框架的使用与原理
#### 1. 线程分类
在Java中,线程主要被划分为两类:用户线程和守护线程(后台线程)。其中,典型的守护线程实例为垃圾回收线程[^1]。
#### 2. 多线程框架的核心概念
Java提供了丰富的API来支持多线程编程。`ThreadPoolExecutor` 是 `java.util.concurrent` 包中的一个重要组件,用于管理线程池并优化性能。以下是其几个关键参数及其作用:
- **corePoolSize**: 表示线程池中保持活动状态的最小线程数。即使这些线程处于空闲状态,也不会被销毁,除非设置了允许超时。
- **maximumPoolSize (maxPoolSize)**: 当任务队列已满且当前线程数小于此值时,线程池将继续创建新线程以执行任务。一旦线程总数达到这个上限,任何额外的任务都将触发拒绝策略[^3]。
- **keepAliveTime**: 非核心线程闲置后的存活时间长度,在这段时间过后未使用的非核心线程会被终止。
- **workQueue**: 存储待处理任务的阻塞队列。常见的实现有 `LinkedBlockingQueue`, `ArrayBlockingQueue` 和 `SynchronousQueue`.
- **ThreadFactory**: 负责创建新线程的对象,默认情况下会生成具有相同优先级以及属于同一组的标准线程。
#### 3. 条件变量的相关方法
对于条件对象Condition而言, 方法 isHeldExclusively() 判断当前线程是否独占锁资源。通常来说,只有当我们自定义实现了某些特定功能或者扩展了AQS(AbstractQueuedSynchronizer),才会涉及到重写此类方法的需求;而在普通的业务场景下,我们更多关注于await(), signal() 及signalAll() 的运用[^2]。
#### 4. 动态调整线程池大小
通过调用 setCorePoolSize(int corePoolSize) 或者 setMaximumPoolSize(int maximumPoolSize), 开发人员可以在程序运行期间灵活更改线程池的工作规模。这使得应用程序能够更好地适应负载变化的情况。另外需要注意的是 largestPoolSize 属性仅用来统计历史数据,并不会影响实际操作行为。
```java
// 创建固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(10);
// 提交任务给线程池执行
executor.submit(() -> {
System.out.println(Thread.currentThread().getName());
});
// 关闭线程池
executor.shutdown();
```
上述代码片段展示了如何利用Executors工厂类快速构建一个拥有十个工作者线程的池子,并向里面提交简单的打印任务最后安全关闭它。
---
如何在线程池中正确配置并使用 Looper?
### 在 Java Android 线程池中正确配置和使用 Looper
在 Android 中,`Looper` 主要用于处理消息循环机制。为了在线程池中正确配置并使用 `Looper`,可以考虑以下几种方式:
#### 方法一:创建带有 Looper 的线程池
可以通过继承 `ThreadFactory` 并覆盖其 `newThread(Runnable r)` 方法来自定义线程工厂,在该方法内部启动一个新的线程,并调用 `Looper.prepare()` 和 `Looper.loop()` 初始化 looper。
```java
public class LooperThreadFactory implements ThreadFactory {
@Override
public Thread newThread(final Runnable runnable) {
return new Thread(() -> {
Looper.prepare();
runnable.run();
Looper.loop();
});
}
}
```
接着利用此自定义的线程工厂去构建线程池实例:
```java
ThreadPoolExecutor executorService = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue,
new LooperThreadFactory()
);
```
这种方法确保了每一个由线程池创建的新线程都会拥有自己的 `Looper` 实例[^1]。
#### 方法二:结合 HandlerThread 创建特定用途的线程池
如果应用程序中有大量需要长时间运行且涉及 UI 更新或者频繁的消息传递的任务,则建议采用 `HandlerThread` 结合固定大小的小型线程池的方式。因为 `HandlerThread` 已经自带了一个 `Looper`,所以可以直接在其上发送消息而无需再次初始化 `Looper`。
对于这种情况下的任务提交,应该先将任务封装成 `Runnable` 对象再交给对应的 `Handler` 去调度执行;而对于那些只需要短暂存在的临时性工作则仍然可以选择普通的无 `Looper` 版本的线程池来进行异步操作[^4]。
需要注意的是,由于 `HandlerThread` 的特殊性质(每个 `HandlerThread` 只能有一个 `Looper`),因此不适合用来作为通用的大规模并发任务处理器,而是更适合于某些具有持续通信需求的服务端口或是后台服务组件[^5]。
#### 关键属性监控与维护
无论采取哪种方案,都应该密切关注线程池的关键状态指标如 `taskCount`, `completedTaskCount`, `largestPoolSize` 等以便及时调整策略优化性能表现[^3]。
阅读全文
相关推荐














