线程池 | 配置指南 | 学习文档

4625 字
23 分钟
线程池 | 配置指南 | 学习文档

线程池 | 配置指南 | 学习文档#

本文面向需要在生产环境配置 Java 线程池的开发者。核心目标:将 ThreadPoolExecutor 的七个参数、任务调度流程、CPU/IO 场景差异、线程数估算方法、队列选型原则、监控指标与动态调优方案整理为可执行的工程规范。重点审查项:线程数是否受下游资源约束、拒绝策略是否可观测、容器环境是否正确读取 CPU 核数。

核心摘要#

  • 问题:手动创建线程存在资源失控、创建开销大、缺乏背压与降级机制三类风险。
  • 方案:使用 ThreadPoolExecutor 显式配置核心线程数、最大线程数、队列、拒绝策略与线程工厂,并通过监控指标闭环调优。
  • 关键约束corePoolSize 不应超过下游最小连接池容量;必须使用有界队列;拒绝策略必须可观测。
  • 目标:读完本文后,能够针对 CPU 密集、IO 密集、混合型三种业务场景给出初始配置,并设计压测与监控方案。

一、为什么需要线程池#

手动为每个请求创建线程,存在以下三类问题:

问题具体表现后果
资源失控每个线程默认约 1MB 栈空间(-Xss 可配置),1000 个并发请求约占用 1GB 堆外内存突发流量下触发 OOM
创建开销线程创建涉及 JVM 栈分配、OS 内核态切换,单次约 10~50μs高频创建时 CPU 与延迟显著上升
管理缺失无法限制并发上限、无法感知任务积压、无法优雅降级故障时缺乏控制手段

线程池提供的核心能力:

  1. 线程复用:降低线程创建与销毁开销。
  2. 有界队列:提供背压机制,防止无限堆积。
  3. 拒绝策略:在容量耗尽时执行降级或告警。

二、ThreadPoolExecutor 核心参数#

ThreadPoolExecutor 的构造函数包含七个参数,必须整体理解:

new ThreadPoolExecutor(
corePoolSize, // 1. 核心线程数
maximumPoolSize, // 2. 最大线程数
keepAliveTime, // 3. 非核心线程空闲存活时间
TimeUnit.SECONDS, // 4. 时间单位
new LinkedBlockingQueue<>(1000), // 5. 工作队列
new NamedThreadFactory("order-exec"), // 6. 线程工厂
new ThreadPoolExecutor.CallerRunsPolicy() // 7. 拒绝策略
);

2.1 corePoolSize 与 maximumPoolSize#

参数含义行为
corePoolSize长期保活的核心线程数即使空闲,默认也不回收(除非调用 allowCoreThreadTimeOut(true)
maximumPoolSize线程池允许创建的最大线程数仅在工作队列满后才会扩张到此值

两种典型策略:

  • 固定大小corePoolSize = maximumPoolSize。无弹性,依赖队列缓冲流量波动。
  • 弹性伸缩corePoolSize < maximumPoolSize。队列满后扩容,空闲线程超时回收。

2.2 keepAliveTime 与 TimeUnit#

  • 控制非核心线程的空闲回收时间。
  • 建议值 30~120 秒。过短导致线程频繁创建销毁,引起 CPU 抖动;过长导致资源闲置。

2.3 工作队列#

队列类型决定排队行为与弹性空间,必须与线程数一起决策。详见第六章。

2.4 线程工厂#

生产环境必须自定义线程工厂,原因:

  • jstack 或 arthas 排查时,"pool-1-thread-1" 无法判断业务归属;
  • 命名清晰的线程(如 "order-exec-1")可快速定位问题线程池。
public class CustomThreadFactory implements ThreadFactory {
private final String prefix;
private final AtomicInteger counter = new AtomicInteger(1);
public CustomThreadFactory(String prefix) {
this.prefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, prefix + "-" + counter.getAndIncrement());
t.setDaemon(false);
t.setUncaughtExceptionHandler((thread, ex) ->
log.error("线程 {} 发生未捕获异常", thread.getName(), ex));
return t;
}
}

2.5 拒绝策略#

当工作队列满且线程数达到 maximumPoolSize 时,新任务触发拒绝策略:

策略行为适用场景风险
AbortPolicy(默认)抛出 RejectedExecutionException核心链路,必须让调用方感知拒绝调用方需捕获异常
CallerRunsPolicy由提交线程自身执行不能丢任务,天然限流可能阻塞调用线程
DiscardPolicy静默丢弃可幂等重试的非关键任务无感知数据丢失,生产慎用
DiscardOldestPolicy丢弃队头最老任务实时性优先,允许淘汰旧请求老请求静默失败

生产建议:优先实现自定义拒绝策略,记录指标、触发告警、执行降级。


三、任务提交与执行流程#

提交任务
当前线程数 < corePoolSize?
│ 是 ──► 创建核心线程并执行
│ 否
将任务放入工作队列
工作队列是否已满?
│ 否 ──► 任务在队列中等待
│ 是
当前线程数 < maximumPoolSize?
│ 是 ──► 创建非核心线程并执行
│ 否
触发拒绝策略

关键认知:只有工作队列满了,线程池才会创建非核心线程。若使用无界队列,maximumPoolSize 永远不会生效。


四、CPU 密集型与 IO 密集型任务#

线程池大小最核心的决策依据是阻塞比(W/C),即等待时间与计算时间的比值。

4.1 CPU 密集型#

典型场景:加密解密、数据压缩、图像处理、复杂排序、JSON 序列化。

  • 线程大部分时间占用 CPU 执行指令。
  • 阻塞比 W/C 约等于 0。
  • 线程切换是纯损耗,不会提升吞吐。
  • 线程数建议N_cpu + 1

4.2 IO 密集型#

典型场景:数据库查询、HTTP 远程调用、文件读写、消息队列消费。

  • 线程大量时间处于 IO 等待状态。
  • 阻塞比 W/C 可达几倍到几十倍。
  • CPU 空闲期间可调度更多线程,提升资源利用率。
  • 线程数建议:根据 Goetz 公式估算,并受下游连接池约束。

4.3 混合型任务#

典型 Web 请求链路示例:

阶段类型耗时占比(示例)
接受 HTTP 请求网络 IO约 5%
参数校验 / 反序列化CPU约 5%
查询数据库IO 等待约 70%
业务规则计算CPU约 10%
写 Redis 缓存IO约 10%

混合场景应分段分析,或通过压测统计整体阻塞比,避免直接套用单一公式。


五、线程数估算方法#

5.1 Little’s Law#

系统稳态下的基本关系:

平均并发数 L = 到达率 λ × 平均响应时间 W

推导出线程数下界:

N_threads ≥ λ × T_response

示例:峰值 QPS = 500,平均 RT = 200ms = 0.2s,则最低需要 500 × 0.2 = 100 个并发线程维持吞吐。

5.2 Brian Goetz 公式#

出处:《Java 并发编程实战》

N_threads = N_cpu × U_cpu × (1 + W/C)
参数含义获取方式
N_cpuCPU 核心数Runtime.getRuntime().availableProcessors()
U_cpu目标 CPU 利用率建议 0.7~0.85,预留余量给 GC / OS / 其他进程
W/C等待时间 / 计算时间Profiler 或 APM 统计

示例:8 核机器,目标利用率 80%,IO 等待 200ms,计算 20ms。

  • W/C = 200 / 20 = 10
  • N = 8 × 0.8 × (1 + 10) = 70.4,取 72

5.3 公式的局限#

  1. 阻塞比难以准确测量:不同流量时段、不同数据量下差异巨大,单次测量值可能误导。
  2. 忽略下游瓶颈:数据库连接池上限 50 时,设 200 个线程只会造成大量线程等待连接,反而劣化延迟。
  3. 假设任务同质:同一池处理轻量查询与重量报表时,平均 W/C 失去意义。

5.4 估算流程#

1. 用 Goetz 公式或 Little's Law 得出理论初始值
2. 对比下游资源上限(DB 连接池、HTTP 连接池),取较小值
3. 结合机器内存校验:线程数 × 1MB(默认栈)不超过可用堆外内存的 50%
4. 以该值作为压测起点,做阶梯加压验证

5.5 常见场景参考值#

场景corePoolSizemaximumPoolSize说明
CPU 密集N_cpu + 1N_cpu + 1+1 防止偶发 IO 阻塞
IO 密集(DB 为主)min(N_cpu × 10, DB 连接池)core × 1.2严格受下游约束
IO 密集(HTTP 为主)N_cpu × (1 + W/C)core × 1.5W/C 需实测
混合型 Web实测后取 10~20× 核数core × 1.25务必压测验证
定时任务 / 批处理2~N_cpucore × 2避免与业务线程池竞争

六、工作队列选型#

队列类型容量行为特征适配场景配套线程数策略
LinkedBlockingQueue(n)有界FIFO,满时触发拒绝策略通用业务,需要背压core = max = N,队列缓冲突发
SynchronousQueue0无缓冲,提交必须立即有线程接收高吞吐低延迟max 较大,newCachedThreadPool 底层
ArrayBlockingQueue(n)有界,数组实现内存局部性好,容量固定严格控制内存core 小,max 大,队列满才扩容
PriorityBlockingQueue无界按优先级出队任务有优先级差异必须控制提交速率
DelayQueue无界到期才出队延迟任务、定时重试core = max = 固定小值

生产红线:禁止使用 Executors.newFixedThreadPool()Executors.newCachedThreadPool()

  • newFixedThreadPool 使用无界 LinkedBlockingQueue,任务堆积可导致 OOM。
  • newCachedThreadPoolmaximumPoolSizeInteger.MAX_VALUE,突发流量下线程数失控。

七、常见反模式#

7.1 全局共用一个线程池#

核心链路与非核心链路共享线程池时,非核心任务突发会挤占核心任务资源。

// 错误:所有任务共用
@Bean("globalExecutor")
ThreadPoolExecutor global() { ... }
// 正确:按业务隔离
@Bean("paymentExecutor") // 核心链路
ThreadPoolExecutor payment() { ... }
@Bean("logExecutor") // 非核心,允许丢弃
ThreadPoolExecutor log() { ... }

7.2 不考虑下游限制盲目设大#

下游 MySQL 连接池上限 50 时,设 500 个线程会导致 450 个线程空等连接,增加上下文切换与排队延迟。

正确做法corePoolSize ≤ 下游最小连接池上限

7.3 keepAliveTime 设置过短#

流量波动场景下,keepAliveTime 过短(如 1 秒)会导致非核心线程频繁创建销毁,造成 CPU 与内存抖动。

正确做法:建议 30~120 秒。

7.4 任务中嵌套提交任务#

// 危险:父任务等待子任务,子任务无法入队 → 死锁
executor.submit(() -> {
Future<?> child = executor.submit(() -> { /* 子任务 */ });
child.get();
});

正确做法:使用 ForkJoinPool 处理父子依赖任务,或为子任务使用独立线程池。

7.5 容器环境不修正 CPU 核数#

Docker 容器限制 2 核时,旧版 JDK 的 Runtime.getRuntime().availableProcessors() 可能返回宿主机 32 核,导致线程数虚高。

// 问题版本
int cores = Runtime.getRuntime().availableProcessors();
// 安全版本:读取容器 CPU 配额
private int getCpuCores() {
String cpuLimit = System.getenv("CPU_LIMIT");
if (cpuLimit != null) return Integer.parseInt(cpuLimit);
try {
Path quotaPath = Paths.get("/sys/fs/cgroup/cpu/cpu.cfs_quota_us");
Path periodPath = Paths.get("/sys/fs/cgroup/cpu/cpu.cfs_period_us");
long quota = Long.parseLong(Files.readString(quotaPath).trim());
long period = Long.parseLong(Files.readString(periodPath).trim());
if (quota > 0) return (int) Math.ceil((double) quota / period);
} catch (Exception ignored) {}
return Runtime.getRuntime().availableProcessors();
}

7.6 线程未命名#

jstack"pool-1-thread-1" 无法判断业务归属,应使用 "order-exec-1" 等命名。


八、企业级配置案例#

8.1 需求分析清单#

配置线程池前必须明确:

  1. 峰值 QPS、平均 RT、P99 RT 是多少?
  2. 任务是否存在外部依赖?下游连接池上限是多少?
  3. SLA 要求:能否丢任务?允许多大延迟?
  4. 容器 / Pod 分配的 CPU 核数是多少?

8.2 订单查询服务配置示例#

场景:8 核 Pod,DB 查询 60ms,本地计算 5ms,W/C ≈ 12,目标 CPU 利用率 80%,DB 连接池上限 50。

计算过程

Goetz 公式:8 × 0.8 × (1 + 12) = 83.2 → 取 84
约束检查:DB 连接池上限 50 → 线程数不应超过 50
内存检查:50 × 1MB = 50MB,在 2GB Pod 内可接受
最终决策:
corePoolSize = 50
maximumPoolSize = 60
queue = LinkedBlockingQueue(300)
keepAliveTime = 60 秒
拒绝策略 = 自定义(记录指标 + 抛异常)

代码实现

@Bean("orderExecutor")
public ThreadPoolExecutor orderExecutor() {
int cores = Runtime.getRuntime().availableProcessors();
int effectiveCores = Math.min(cores, Integer.parseInt(
System.getenv().getOrDefault("CPU_LIMIT", String.valueOf(cores))));
int dbPoolSize = 50;
int coreSize = Math.min(effectiveCores * 10, dbPoolSize);
int maxSize = (int) (coreSize * 1.2);
int queueCap = coreSize * 6;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
coreSize, maxSize,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(queueCap),
new CustomThreadFactory("order-exec"),
new MetricsRejectedHandler("order")
);
executor.allowCoreThreadTimeOut(false);
return executor;
}

自定义拒绝处理器

public class MetricsRejectedHandler implements RejectedExecutionHandler {
private final String poolName;
public MetricsRejectedHandler(String poolName) {
this.poolName = poolName;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
Metrics.counter("threadpool.rejected", "pool", poolName).increment();
log.error("[{}] 任务被拒绝,队列积压:{} 活跃线程:{} 最大线程:{}",
poolName, e.getQueue().size(), e.getActiveCount(), e.getMaximumPoolSize());
throw new RejectedExecutionException("Pool " + poolName + " is saturated");
}
}

8.3 压测验证方案#

阶梯加压节奏:

10 并发 → 稳定 2 分钟 → 记录基准
50 并发 → 稳定 2 分钟 → 记录吞吐 / RT / 队列深度
100 并发 → 稳定 2 分钟 → 观察是否积压
150 并发 → 稳定 2 分钟 → 观察 P99 劣化点
200 并发 → 稳定 2 分钟 → 寻找拒绝临界点

压测期间重点采集:

pool.getActiveCount(); // 当前活跃线程数
pool.getQueue().size(); // 排队任务数
pool.getCompletedTaskCount(); // 已完成任务总数
pool.getLargestPoolSize(); // 历史最大线程数
pool.getTaskCount(); // 提交的总任务数

九、动态线程池#

9.1 动态调整原理#

ThreadPoolExecutor 支持运行时修改核心参数:

executor.setCorePoolSize(newCoreSize);
executor.setMaximumPoolSize(newMaxSize);

结合 Apollo / Nacos 配置中心可实现秒级热更新。

9.2 实现示例#

@Component
public class DynamicThreadPoolManager {
@Autowired
private ThreadPoolExecutor orderExecutor;
@NacosConfigListener(dataId = "thread-pool-config", groupId = "DEFAULT_GROUP")
public void onConfigChange(String configJson) {
ThreadPoolConfig cfg = JSON.parseObject(configJson, ThreadPoolConfig.class);
int newCore = cfg.getCoreSize();
int newMax = cfg.getMaxSize();
// 扩大时先改 max,缩小时先改 core
if (newCore > orderExecutor.getMaximumPoolSize()) {
orderExecutor.setMaximumPoolSize(newMax);
orderExecutor.setCorePoolSize(newCore);
} else {
orderExecutor.setCorePoolSize(newCore);
orderExecutor.setMaximumPoolSize(newMax);
}
log.info("线程池动态调整完成 pool=order core={} max={}", newCore, newMax);
}
}

9.3 队列容量动态修改#

标准 BlockingQueue 容量在构造时固定。如需动态队列,可选:

  1. 自实现 ResizableLinkedBlockingQueue:重写 capacity setter,加锁保证并发安全。
  2. 开源方案
    • dynamic-tp(京东开源):支持参数热更新、监控、告警一体化。
    • Hippo4j(美团团队维护):企业级动态线程池框架,支持多注册中心。

十、可观测性:监控与告警#

10.1 Prometheus 指标暴露#

public static void registerToPrometheus(ThreadPoolExecutor pool, String name) {
MeterRegistry registry = Metrics.globalRegistry;
Gauge.builder("threadpool.active", pool, ThreadPoolExecutor::getActiveCount)
.tag("pool", name).description("活跃线程数").register(registry);
Gauge.builder("threadpool.pool_size", pool, ThreadPoolExecutor::getPoolSize)
.tag("pool", name).description("当前线程总数").register(registry);
Gauge.builder("threadpool.queue_size", pool, p -> p.getQueue().size())
.tag("pool", name).description("队列积压任务数").register(registry);
Gauge.builder("threadpool.utilization", pool,
p -> (double) p.getActiveCount() / p.getCorePoolSize())
.tag("pool", name).description("核心线程利用率").register(registry);
Gauge.builder("threadpool.largest_pool_size", pool, ThreadPoolExecutor::getLargestPoolSize)
.tag("pool", name).description("历史最大线程数").register(registry);
}

10.2 AlertManager 告警规则#

groups:
- name: threadpool_alerts
rules:
- alert: ThreadPoolHighUtilization
expr: threadpool_utilization > 0.85
for: 2m
labels:
severity: warning
annotations:
summary: "线程池 {{ $labels.pool }} 利用率超过 85%"
- alert: ThreadPoolQueueBacklog
expr: threadpool_queue_size / threadpool_queue_capacity > 0.7
for: 1m
labels:
severity: warning
annotations:
summary: "线程池 {{ $labels.pool }} 队列积压超过 70%"
- alert: ThreadPoolRejection
expr: increase(threadpool_rejected_total[1m]) > 0
for: 0m
labels:
severity: critical
annotations:
summary: "线程池 {{ $labels.pool }} 出现任务拒绝"
- alert: ThreadPoolMaxSizeReached
expr: threadpool_pool_size >= threadpool_max_size
for: 3m
labels:
severity: warning
annotations:
summary: "线程池 {{ $labels.pool }} 线程数触达最大值,持续 3 分钟"

10.3 告警阈值参考#

指标WarningCritical含义
活跃线程 / 核心线程数> 80%> 95%线程饱和,即将排队
队列积压量> 队列容量 50%> 80%消费跟不上,延迟上涨
被拒绝任务数(1 分钟)> 0> 10系统过载
线程数触达 maximumPoolSize持续 1 分钟持续 5 分钟需要扩容或限流

十一、性能调优建议#

11.1 线程数调优#

  • 初始值:使用 Goetz 公式或历史 QPS/RT 数据估算。
  • 约束校验:确保 corePoolSize ≤ min(DB 连接池, HTTP 连接池, 内存可承载线程数)
  • 压测验证:以阶梯加压找到吞吐拐点,将 corePoolSize 设置在拐点并发量的 70%~80%。
  • 动态调整:流量波动明显的服务接入动态线程池。

11.2 队列深度调优#

  • 队列容量不宜过大:过大会隐藏延迟问题,导致 P99 劣化。
  • 经验公式:queueCapacity = corePoolSize × 平均 RT(秒) × 安全系数(2~3)
  • 需要背压的场景使用有界队列,拒绝策略选择 CallerRunsPolicy 或自定义策略。

11.3 GC 与内存调优#

  • 关注线程栈内存占用:默认 1MB/线程,可通过 -Xss 调整。
  • 高频创建/销毁线程会增加 Native Memory 分配压力,尽量复用线程。
  • 容器环境开启 -XX:+UseContainerSupport(JDK 8u191+)。

11.4 上下文切换调优#

  • cs(上下文切换次数)/ 任务数 持续升高时,说明线程数过多。
  • 使用 vmstatpidstat -w 监控上下文切换频率。
  • 在线程饱和前扩容机器或优化任务计算逻辑。

十二、常见问题解答(FAQ)#

Q1:corePoolSizemaximumPoolSize 应该设成一样吗?#

A:不一定。固定大小(core = max)适合负载稳定的场景,实现简单;弹性伸缩(core < max)适合流量波动大、需要应对突发的场景。生产环境更推荐后者,配合有界队列使用。

Q2:为什么线程池达到了 maximumPoolSize 但 CPU 使用率仍然很低?#

A:可能原因:

  1. 线程大部分时间阻塞在 IO 等待,CPU 未被有效利用;
  2. 下游服务(数据库、缓存、HTTP 接口)成为瓶颈;
  3. 锁竞争严重,线程实际并行度不足。

应通过 APM 或 Profiler 定位具体阻塞点,而不是简单增加线程数。

Q3:任务被拒绝时应该选择哪种策略?#

A:核心链路推荐 AbortPolicy 或自定义策略(记录指标 + 抛异常),让调用方感知并降级;非核心但不可丢任务的场景可选 CallerRunsPolicy;可丢弃的非关键任务可选 DiscardPolicyDiscardOldestPolicy

Q4:使用 CompletableFuture 时如何指定自定义线程池?#

ACompletableFuture 默认使用 ForkJoinPool.commonPool(),可能不适合业务场景。应显式传入:

CompletableFuture.supplyAsync(() -> fetchOrder(orderId), orderExecutor)
.thenApplyAsync(this::enrichOrder, orderExecutor);

Q5:Spring 的 @Async 默认线程池有什么问题?#

A:Spring 默认使用 SimpleAsyncTaskExecutor,每次任务都新建线程,且队列无界。生产环境应通过 ThreadPoolTaskExecutor 自定义:

@Bean("taskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(16);
executor.setMaxPoolSize(32);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}

Q6:如何优雅关闭线程池?#

A:使用 shutdown() + awaitTermination() 组合:

executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}

Q7:allowCoreThreadTimeOut(true) 是否推荐?#

A:适合流量波动极大的场景,可在低峰期回收核心线程节省资源。但会增加高峰期线程创建开销,核心链路建议保持默认 false


十三、决策速查表#

场景corePoolSizemaximumPoolSize队列拒绝策略
CPU 密集N_cpu + 1N_cpu + 1有界或小容量AbortPolicy
IO 密集(有下游限制)min(公式值, 下游连接池)core × 1.2有界自定义 + 指标
高吞吐低延迟N_cpu × 2较大SynchronousQueueCallerRunsPolicy
批处理 / 定时任务2~N_cpucore × 2有界CallerRunsPolicy
混合型 Web实测后 10~20× 核数core × 1.25有界自定义 + 指标

总结#

  1. 永远不用 Executors 工厂方法,必须显式构造 ThreadPoolExecutor
  2. 必须使用有界队列,无界队列是 OOM 隐患。
  3. corePoolSize 不超过下游最小连接池,这是物理约束。
  4. 拒绝策略必须可观测,静默丢弃在生产环境等于数据黑洞。
  5. 暴露监控指标并设置告警,线程池问题不能靠感觉发现。

合理工程流程:

公式估算 → 约束校验 → 压测验证 → 监控落地 → 动态调整

参考资料#

  • 《Java 并发编程实战》Brian Goetz
  • 阿里巴巴《Java 开发手册》
  • dynamic-tp
  • Hippo4j
线程池 | 配置指南 | 学习文档
https://tblog.mmzhiku.xyz/posts/projects/projects-java-thread-pool-configuration/
作者
MmzMing
发布于
2026-05-07
许可协议
CC BY-NC-SA 4.0

评论区

看板娘
公告
友链 互换友链

正在招募技术类博客友链,要求原创、稳定更新。点击了解更多。

查看详情
维护 服务器升级

本周日凌晨 2:00-4:00 进行服务器维护,期间站点可能短暂无法访问。

欢迎 关于我的介绍

欢迎来到我的博客,我是深耕java、python和react技术开发。热爱技术、持续学习,欢迎同好交流探讨,也欢迎大佬互换友链。

查看详情
音乐
封面

音乐

暂未播放

0:00
0:00
暂无歌词
标签
# AI 6 # 认证 5 # 安全 4 # 登录 3 # Skill 2 # Redis 2 # Bitmap 2 # 部署 2 # Java 2 # 并发编程 2 # 性能优化 2 # 前端 1 # 博客 1 # Prompt 1 # 工作流 1 # RAG 1 # Cloudflare 1 # 缓存设计 1 # 高性能 1 # Bot 1 # Umami 1 # Vercel 1 # 线程池 1 # 虚拟线程 1 # 分布式 1 # JWT 1 # OAuth2 1 # MinIO 1 # 文件存储 1 # 扫码登录 1 # WebSocket 1 # Agent 1 # Oracle 1 # 数据库 1
目录

隐私政策

更新日期: 2026/5/19
生效日期: 2026/5/19

导言#

MmzMing的知识库 是一款由 MmzMing(以下简称“我们”)提供的产品。您在使用我们的服务时,我们可能会收集和使用您的相关信息。我们希望通过本《隐私政策》向您说明,在使用我们的服务时,我们如何收集、使用、储存和分享这些信息,以及我们为您提供的访问、更新、控制和保护这些信息的方式。

本《隐私政策》与您所使用的 MmzMing的知识库 服务息息相关,希望您仔细阅读,在需要时,按照本《隐私政策》的指引,作出您认为适当的选择。本《隐私政策》中涉及的相关技术词汇,我们尽量以简明扼要的表述,并提供进一步说明的链接,以便您的理解。

您使用或继续使用我们的服务,即意味着同意我们按照本《隐私政策》收集、使用、储存和分享您的相关信息。

如对本《隐私政策》或相关事宜有任何问题,请通过 784774835@qq.com 与我们联系。

1. 我们收集的信息#

我们或我们的第三方合作伙伴提供服务时,可能会收集、储存和使用下列与您有关的信息。如果您不提供相关信息,可能无法注册成为我们的用户或无法享受我们提供的某些服务,或者无法达到相关服务拟达到的效果。

  • 个人信息:您在注册账户或使用我们的服务时,向我们提供的相关个人信息,例如电话号码、电子邮件等。
  • 日志信息:指您使用我们的服务时,系统可能通过 cookies、标识符及相关技术收集的信息,包括您的 设备信息浏览信息点击信息,并将该等信息储存为日志信息,为您提供个性化的用户体验、保障服务安全。您可以通过浏览器设置拒绝或管理 cookie、标识符或相关技术的使用。
  • 位置信息:指您开启设备定位功能并使用我们基于位置提供的相关服务时,收集的有关您位置的信息,包括:
    • 您通过具有定位功能的移动设备使用我们的服务时,通过 GPS 或 WiFi 等方式收集的您的地理位置信息;
    • 您可以通过关闭定位功能,停止对您的地理位置信息的收集。

2. 信息的存储#

2.1 信息存储的方式和期限#

我们会通过安全的方式存储您的信息,包括本地存储(例如利用 APP 进行数据缓存)、数据库和服务器日志。

一般情况下,我们只会在为实现服务目的所必需的时间内或法律法规规定的条件下存储您的个人信息。

2.2 信息存储的地域#

我们会按照法律法规规定,将境内收集的用户个人信息存储于中国境内。

目前我们不会跨境传输或存储您的个人信息。将来如需跨境传输或存储的,我们会向您告知信息出境的目的、接收方、安全保证措施和安全风险,并征得您的同意。

2.3 产品或服务停止运营时的通知#

当我们的产品或服务发生停止运营的情况时,我们将以推送通知、公告等形式通知您,并在合理期限内删除您的个人信息或进行匿名化处理,法律法规另有规定的除外。

3. 信息安全#

我们使用各种安全技术和程序,以防信息的丢失、不当使用、未经授权阅览或披露。例如,在某些服务中,我们将利用加密技术(例如 SSL)来保护您提供的个人信息。但请您理解,由于技术的限制以及可能存在的各种恶意手段,在互联网行业,即便竭尽所能加强安全措施,也不可能始终保证信息百分之百的安全。您需要了解,您接入我们的服务所用的系统和通讯网络,有可能因我们可控范围外的因素而出现问题。

4. 我们如何使用信息#

我们可能将在向您提供服务的过程之中所收集的信息用作下列用途:

  • 向您提供服务;
  • 在我们提供服务时,用于身份验证、客户服务、安全防范、诈骗监测、存档和备份用途,确保我们向您提供的产品和服务的安全性;
  • 帮助我们设计新服务,改善我们现有服务;
  • 使我们更加了解您如何接入和使用我们的服务,从而针对性地回应您的个性化需求,例如语言设定、位置设定、个性化的帮助服务和指示,或对您和其他用户作出其他方面的回应;
  • 向您提供与您更加相关的广告以替代普遍投放的广告;
  • 评估我们服务中的广告和其他促销及推广活动的效果,并加以改善;
  • 软件认证或管理软件升级;
  • 让您参与有关我们产品和服务的调查。

5. 信息共享#

目前,我们不会主动共享或转让您的个人信息至第三方,如存在其他共享或转让您的个人信息或您需要我们将您的个人信息共享或转让至第三方情形时,我们会直接或确认第三方征得您对上述行为的明示同意。

为了投放广告,评估、优化广告投放效果等目的,我们需要向广告主及其代理商等第三方合作伙伴共享您的部分数据,要求其严格遵守我们关于数据隐私保护的措施与要求,包括但不限于根据数据保护协议、承诺书及相关数据处理政策进行处理,避免识别出个人身份,保障隐私安全。

我们不会向合作伙伴分享可用于识别您个人身份的信息(例如您的姓名或电子邮件地址),除非您明确授权。

我们不会对外公开披露所收集的个人信息,如必须公开披露时,我们会向您告知此次公开披露的目的、披露信息的类型及可能涉及的敏感信息,并征得您的明示同意。

随着我们业务的持续发展,我们有可能进行合并、收购、资产转让等交易,我们将告知您相关情形,按照法律法规及不低于本《隐私政策》所要求的标准继续保护或要求新的控制者继续保护您的个人信息。

另外,根据相关法律法规及国家标准,以下情形中,我们可能会共享、转让、公开披露个人信息无需事先征得您的授权同意:

  • 与国家安全、国防安全直接相关的;
  • 与公共安全、公共卫生、重大公共利益直接相关的;
  • 犯罪侦查、起诉、审判和判决执行等直接相关的;
  • 出于维护个人信息主体或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
  • 个人信息主体自行向社会公众公开个人信息的;
  • 从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。

6. 您的权利#

在您使用我们的服务期间,我们可能会视产品具体情况为您提供相应的操作设置,以便您可以查询、删除、更正或撤回您的相关个人信息,您可参考相应的具体指引进行操作。此外,我们还设置了投诉举报渠道,您的意见将会得到及时的处理。如果您无法通过上述途径和方式行使您的个人信息主体权利,您可以通过本《隐私政策》中提供的联系方式提出您的请求,我们会按照法律法规的规定予以反馈。

当您决定不再使用我们的产品或服务时,可以申请注销账户。注销账户后,除法律法规另有规定外,我们将删除或匿名化处理您的个人信息。

7. 变更#

我们可能适时修订本《隐私政策》的条款。当变更发生时,我们会在版本更新时向您提示新的《隐私政策》,并向您说明生效日期。请您仔细阅读变更后的《隐私政策》内容,若您继续使用我们的服务,即表示您同意我们按照更新后的《隐私政策》处理您的个人信息。

8. 未成年人保护#

我们鼓励父母或监护人指导未满十八岁的未成年人使用我们的服务。我们建议未成年人鼓励他们的父母或监护人阅读本《隐私政策》,并建议未成年人在提交的个人信息之前寻求父母或监护人的同意和指导。