跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Javajava

Java 并发编程:核心原理、实战与避坑

综述由AI生成Java 并发编程涉及多线程安全、JVM 内存模型及同步机制。文章解析了线程创建方式、生命周期、synchronized 与 Lock 区别、线程池参数优化及常用工具类 CountDownLatch 等。重点指出 volatile 误用、线程池 OOM、死锁等常见坑点,并提供生产环境配置建议与排查工具,帮助开发者掌握高效安全的并发代码编写方法。

晚风叙旧发布于 2026/3/15更新于 2026/4/2616 浏览
Java 并发编程:核心原理、实战与避坑

并发编程是 Java 开发的核心技能,也是面试高频考点与生产环境故障高发区。多数开发者在使用多线程时,常面临线程安全(如竞态条件、数据不一致)、死锁、性能瓶颈(如线程上下文切换过多)等问题,且对底层原理(JVM 内存模型、线程调度)理解模糊。本文将从并发编程核心概念切入,深度解析线程创建方式、同步机制、线程池原理、并发工具类等关键知识点,结合 10+ 实战案例拆解常见坑点(如 synchronized 锁升级、volatile 可见性陷阱),提供一套'原理 + 实践 + 优化'的完整方法论,帮助开发者从根源上掌握并发编程,写出高效、安全的多线程代码。

一、并发编程核心概念与底层原理

1. 为什么需要并发编程?

在多核 CPU 时代,并发编程的核心价值在于充分利用硬件资源,提升程序执行效率:

  • 提高吞吐量:同时处理多个任务(如 Web 服务器同时响应上千个请求);
  • 降低响应时间:将耗时操作(如 IO、网络请求)异步化,避免阻塞主线程;
  • 提升资源利用率:CPU、内存、IO 设备并行工作,减少资源闲置。
2. 核心概念辨析(避免混淆)
概念核心定义举例场景
进程操作系统资源分配的最小单位(拥有独立内存空间、文件句柄等)一个 Java 应用程序(JVM 进程)
线程进程内的执行单元(共享进程资源,CPU 调度的最小单位)Java 程序中的 Thread 实例
协程用户态轻量级线程(无内核调度开销,由程序自身控制切换)Spring WebFlux 中的异步任务、Go 语言的 goroutine
并发(Concurrency)多个任务在同一时间段内交替执行(CPU 切换快,看似同时)单 CPU 核心下多线程处理请求
并行(Parallelism)多个任务在同一时刻同时执行(依赖多核 CPU)四核 CPU 同时处理 4 个线程任务
线程安全多线程并发访问共享资源时,程序行为符合预期(无数据污染、死锁等问题)并发环境下 i++ 操作结果正确
3. 底层原理:JVM 内存模型(JMM)

并发问题的根源在于多线程对共享变量的可见性、原子性、有序性问题,而 JMM 正是为解决这些问题而生:

  • 可见性:一个线程修改共享变量后,其他线程能立即看到修改结果(如 volatile 关键字的内存屏障作用);
  • 原子性:操作不可分割(如 synchronized/Lock 保证代码块原子执行,CAS 保证单个变量原子操作);
  • 有序性:程序执行顺序符合代码逻辑(避免 CPU 指令重排序导致的并发问题,如 volatile 禁止重排序)。
关键细节:
  • 共享变量存储在主内存,线程操作时会将变量加载到工作内存(寄存器/缓存),操作后写回主内存;
  • 多线程并发时,若未做同步处理,可能出现'工作内存与主内存数据不一致'(可见性问题)、'指令重排序导致逻辑错乱'(有序性问题)。

二、Java 并发编程核心技术拆解(含实战)

1. 线程创建与生命周期
(1)三种创建方式(对比与选型)
创建方式核心原理优点
缺点
实战示例
继承 Thread 类重写 run() 方法,直接调用 start() 启动线程实现简单,代码简洁无法继承其他类(Java 单继承)class MyThread extends Thread { @Override public void run() {} }
实现 Runnable 接口实现 run() 方法,通过 Thread 实例包装启动可继承其他类,灵活性高无法直接返回结果(需配合 Future)class MyRunnable implements Runnable { @Override public void run() {} }
实现 Callable 接口实现 call() 方法,通过 FutureTask 包装,支持返回结果和异常抛出支持返回结果、异常处理实现稍复杂,需配合线程池使用class MyCallable implements Callable<Integer> { @Override public Integer call() {} }
(2)线程生命周期(6 种状态)

Java 线程状态定义在 Thread.State 枚举中,状态流转是面试核心:

  • NEW:线程创建未启动(未调用 start());
  • RUNNABLE:线程正在执行或等待 CPU 调度(包含操作系统的'就绪'和'运行'状态);
  • BLOCKED:线程阻塞等待锁(如 synchronized 未获取到锁时);
  • WAITING:线程无限期等待(如 Object.wait()、LockSupport.park(),需其他线程唤醒);
  • TIMED_WAITING:线程限时等待(如 Thread.sleep(1000)、Object.wait(1000));
  • TERMINATED:线程执行完毕。
关键避坑:
  • 线程调用 start() 后不能重复启动(会抛出 IllegalThreadStateException);
  • Thread.sleep() 不会释放锁,Object.wait() 会释放锁(需在 synchronized 代码块中调用)。
2. 同步机制:synchronized 与 Lock 详解

同步机制的核心是保证临界区代码原子执行,避免多线程并发冲突,Java 提供两种核心方案:

(1)synchronized(隐式锁,JVM 层面实现)
  • 核心特性:可重入、非公平锁、自动释放锁(代码块执行完毕或异常时);
  • 锁的范围:
    • 修饰方法:锁对象为当前实例(非静态方法)或类对象(静态方法);
    • 修饰代码块:锁对象为括号内的对象(如 this、Class 对象、自定义对象);
  • 底层原理:基于对象头的 Mark Word 实现,锁升级过程(无锁→偏向锁→轻量级锁→重量级锁)是性能优化的关键:
    • 偏向锁:单线程场景下避免锁竞争,提高效率;
    • 轻量级锁:多线程交替执行,通过 CAS 自旋获取锁,避免阻塞;
    • 重量级锁:多线程同时竞争,通过操作系统互斥量实现,会导致线程阻塞(性能较差)。
实战示例:synchronized 解决 i++ 线程安全问题
public class SynchronizedDemo {
    private int count = 0;

    // 修饰方法(锁当前实例)
    public synchronized void increment() {
        count++; // 临界区代码(原子执行)
    }

    public static void main(String[] args) throws InterruptedException {
        SynchronizedDemo demo = new SynchronizedDemo();
        // 启动 1000 个线程,每个线程执行 1000 次 increment
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 1000; i++) {
            executor.submit(demo::increment);
        }
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);
        System.out.println("最终 count 值:" + demo.count); // 输出 1000000(线程安全)
    }
}
(2)Lock(显式锁,API 层面实现)

java.util.concurrent.locks.Lock 接口,核心实现类 ReentrantLock(可重入锁),相比 synchronized 更灵活:

  • 核心特性:可重入、支持公平锁/非公平锁、可中断锁、超时获取锁、条件变量(Condition);
  • 核心方法:
    • lock():获取锁(阻塞);
    • tryLock():尝试获取锁(非阻塞,返回 boolean);
    • tryLock(long time, TimeUnit unit):超时获取锁;
    • unlock():释放锁(必须在 finally 中调用,避免死锁);
  • 适用场景:需要灵活控制锁(如超时重试、公平锁)、多条件等待(如生产者 - 消费者模型)。
实战示例:ReentrantLock 实现生产者 - 消费者模型
public class LockProducerConsumer {
    private final Lock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition(); // 非空条件
    private final Condition notFull = lock.newCondition(); // 非满条件
    private final Queue<Integer> queue = new LinkedList<>();
    private static final int CAPACITY = 10; // 队列容量

    // 生产者
    public void produce(int data) throws InterruptedException {
        lock.lock();
        try {
            // 队列满时等待
            while (queue.size() == CAPACITY) {
                notFull.await(); // 释放锁,等待 notFull 信号
            }
            queue.offer(data);
            System.out.println("生产者生产:" + data);
            notEmpty.signal(); // 唤醒消费者(队列非空)
        } finally {
            lock.unlock(); // 必须在 finally 释放锁
        }
    }

    // 消费者
    public Integer consume() throws InterruptedException {
        lock.lock();
        try {
            // 队列为空时等待
            while (queue.isEmpty()) {
                notEmpty.await(); // 释放锁,等待 notEmpty 信号
            }
            Integer data = queue.poll();
            System.out.println("消费者消费:" + data);
            notFull.signal(); // 唤醒生产者(队列非满)
            return data;
        } finally {
            lock.unlock();
        }
    }
}
(3)synchronized 与 ReentrantLock 对比选型
对比维度synchronizedReentrantLock
锁实现层面JVM 层面(隐式锁)API 层面(显式锁)
锁类型非公平锁(默认),不可配置公平锁/非公平锁(可通过构造函数配置)
锁释放自动释放(代码块执行完毕/异常)手动释放(必须在 finally 中调用 unlock())
功能扩展基础同步功能,无额外 API支持中断、超时、条件变量、锁尝试
性能JDK1.6 后优化(锁升级),性能接近 Lock高并发场景下性能更优,灵活度高
适用场景简单同步场景(如单例模式、简单计数器)复杂同步场景(如多条件等待、超时重试)
3. 线程池:核心原理与参数优化

线程池是并发编程的'性能利器',其核心价值是复用线程、控制线程数量、减少线程创建销毁开销,避免'线程爆炸'(如无限制创建线程导致 OOM)。

(1)核心原理:ThreadPoolExecutor

Java 线程池的核心实现类是 ThreadPoolExecutor,构造函数参数决定线程池行为:

public ThreadPoolExecutor(int corePoolSize,      // 核心线程数(常驻线程,即使空闲也不销毁)
                          int maximumPoolSize,  // 最大线程数(核心线程 + 临时线程的总上限)
                          long keepAliveTime,   // 临时线程空闲存活时间
                          TimeUnit unit,        // keepAliveTime 的时间单位
                          BlockingQueue<Runnable> workQueue, // 任务阻塞队列(核心线程满时存储任务)
                          ThreadFactory threadFactory,       // 线程创建工厂(自定义线程名称、优先级等)
                          RejectedExecutionHandler handler)  // 任务拒绝策略(队列满 + 最大线程数时的处理方式)
(2)任务执行流程(必记)
  1. 提交任务时,先判断核心线程是否空闲:若空闲则直接执行,否则创建核心线程;
  2. 核心线程满时,将任务加入阻塞队列;
  3. 队列满时,创建临时线程执行任务;
  4. 临时线程满(达到 maximumPoolSize)且队列满时,触发拒绝策略。
(3)拒绝策略(4 种默认实现)
拒绝策略类核心逻辑适用场景
AbortPolicy(默认)直接抛出 RejectedExecutionException 异常不允许任务丢失的场景(如金融交易)
CallerRunsPolicy由提交任务的线程(如主线程)自己执行任务允许任务延迟执行,不希望抛出异常的场景
DiscardPolicy直接丢弃任务,不抛出异常任务可丢失的场景(如日志收集)
DiscardOldestPolicy丢弃队列中最旧的任务,再尝试提交当前任务任务有优先级,新任务比旧任务重要的场景
(4)常见线程池(Executors 工具类)

Executors 提供了 4 种预定义线程池,但生产环境不建议直接使用(存在 OOM 风险):

  • Executors.newFixedThreadPool(n):固定核心线程数,无临时线程(maximumPoolSize=corePoolSize),队列无界(LinkedBlockingQueue)→ 队列满时 OOM;
  • Executors.newCachedThreadPool():核心线程数 0,临时线程无上限(maximumPoolSize=Integer.MAX_VALUE)→ 线程爆炸 OOM;
  • Executors.newSingleThreadExecutor():单核心线程,队列无界 → 队列满时 OOM;
  • Executors.newScheduledThreadPool(n):定时任务线程池,核心线程数 n,支持延迟/周期性执行任务。
(5)生产环境线程池配置优化(实战)

线程池参数需根据业务场景(CPU 密集型/IO 密集型)调整:

  • CPU 密集型任务(如计算、排序):线程数=CPU 核心数 +1(避免 CPU 空闲,充分利用核心);
  • IO 密集型任务(如数据库查询、网络请求):线程数=CPU 核心数×2+1(IO 操作时线程阻塞,多线程可提高吞吐量);
实战配置示例:
// 1. 获取 CPU 核心数
int cpuCoreNum = Runtime.getRuntime().availableProcessors();
// 2. 配置 IO 密集型线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    cpuCoreNum * 2,                      // 核心线程数
    cpuCoreNum * 2 + 1,                  // 最大线程数
    60L,                                 // 临时线程空闲存活时间
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(1000),      // 有界队列(避免 OOM),容量根据业务调整
    new ThreadFactory() {                // 自定义线程工厂(便于问题排查)
        private final AtomicInteger count = new AtomicInteger(0);
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("biz-thread-" + count.incrementAndGet());
            thread.setPriority(Thread.NORM_PRIORITY);
            return thread;
        }
    },
    new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略(IO 密集型允许延迟)
);
4. 并发工具类:CountDownLatch、CyclicBarrier、Semaphore

Java 并发包(java.util.concurrent)提供了多种工具类,简化复杂并发场景的开发:

(1)CountDownLatch(倒计时器)
  • 核心功能:让主线程等待多个子线程执行完毕后再继续执行(不可重复使用);
  • 原理:初始化时指定计数器值,子线程执行完毕调用 countDown() 减 1,主线程调用 await() 阻塞,直到计数器为 0。
实战场景:主线程等待 3 个任务线程执行完毕
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3); // 计数器=3
        // 启动 3 个任务线程
        for (int i = 1; i <= 3; i++) {
            int taskId = i;
            new Thread(() -> {
                try {
                    System.out.println("任务" + taskId + "执行中...");
                    Thread.sleep(1000); // 模拟任务执行
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    latch.countDown(); // 任务执行完毕,计数器减 1
                }
            }).start();
        }
        latch.await(); // 主线程阻塞,等待计数器为 0
        System.out.println("所有任务执行完毕,主线程继续执行");
    }
}
(2)CyclicBarrier(循环屏障)
  • 核心功能:让多个线程到达某个'屏障'后阻塞,直到所有线程都到达屏障,再一起继续执行(可重复使用);
  • 区别于 CountDownLatch:CyclicBarrier 是'线程互相等待',CountDownLatch 是'主线程等待子线程';支持重置计数器(reset())。
实战场景:3 个线程同时开始执行任务
public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("所有线程已到达屏障,开始同步执行...");
        }); // 计数器=3,屏障触发时执行回调
        for (int i = 1; i <= 3; i++) {
            int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程" + threadId + "正在前往屏障...");
                    Thread.sleep(threadId * 1000); // 模拟不同到达时间
                    barrier.await(); // 到达屏障,阻塞等待其他线程
                    System.out.println("线程" + threadId + "开始执行任务");
                } catch (InterruptedException | BrokenBarrierException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
        }
    }
}
(3)Semaphore(信号量)
  • 核心功能:控制同时访问某个资源的线程数量(限流);
  • 原理:初始化时指定许可数,线程获取许可(acquire())后才能访问资源,访问完毕释放许可(release()),许可数为 0 时线程阻塞。
实战场景:限制最多 2 个线程同时访问数据库连接
public class SemaphoreDemo {
    private static final Semaphore semaphore = new Semaphore(2); // 最多 2 个许可
    private static final List<String> dbConnections = Arrays.asList("conn1", "conn2", "conn3");

    public static void main(String[] args) {
        // 启动 5 个线程竞争访问数据库连接
        for (int i = 1; i <= 5; i++) {
            int threadId = i;
            new Thread(() -> {
                try {
                    semaphore.acquire(); // 获取许可(限流)
                    String conn = dbConnections.get(threadId % 3);
                    System.out.println("线程" + threadId + "获取连接:" + conn);
                    Thread.sleep(1000); // 模拟数据库操作
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    semaphore.release(); // 释放许可
                    System.out.println("线程" + threadId + "释放连接");
                }
            }).start();
        }
    }
}

三、并发编程常见坑点与避坑指南

1. 坑点 1:volatile 关键字的误用
  • 错误认知:认为 volatile 能保证原子性(如 volatile int i=0; i++ 线程安全);
  • 正确认知:volatile 仅保证可见性和有序性,不保证原子性;
  • 避坑方案:原子操作使用 AtomicInteger(CAS 实现),复杂逻辑使用 synchronized/Lock。
2. 坑点 2:线程池参数不合理导致 OOM
  • 错误场景:使用 Executors.newFixedThreadPool()(无界队列),高并发下任务堆积导致 OOM;
  • 避坑方案:
    • 自定义 ThreadPoolExecutor,使用有界队列(如 ArrayBlockingQueue);
    • 合理设置队列容量和最大线程数,避免任务堆积;
    • 选择合适的拒绝策略(如 CallerRunsPolicy)。
3. 坑点 3:死锁问题
  • 死锁条件:资源互斥、持有并等待、不可剥夺、循环等待;
  • 实战案例:线程 A 持有锁 1,等待锁 2;线程 B 持有锁 2,等待锁 1;
  • 避坑方案:
    • 统一锁获取顺序(如线程 A、B 都先获取锁 1,再获取锁 2);
    • 使用 ReentrantLock.tryLock(time, unit) 超时获取锁,避免无限等待;
    • 定期检测死锁(如通过 jstack 命令分析线程堆栈)。
4. 坑点 4:synchronized 锁范围过大导致性能问题
  • 错误场景:将整个方法加锁(如 public synchronized void method()),导致所有线程串行执行;
  • 避坑方案:
    • 缩小锁范围(仅对临界区代码加锁);
    • 使用更灵活的 Lock(如 ReentrantLock),支持非阻塞获取锁;
    • 无状态方法避免加锁(无需共享资源)。

四、并发编程黄金法则(必记)

  1. 优先使用线程池,而非直接创建线程:复用线程、控制数量,避免 OOM 和性能开销;
  2. 慎用 synchronized,灵活选择锁机制:简单场景用 synchronized,复杂场景用 ReentrantLock;
  3. volatile 不保证原子性:原子操作优先用 JUC 原子类(AtomicXXX);
  4. 避免线程阻塞的过度使用:IO 密集型任务用异步编程(如 CompletableFuture),减少线程阻塞;
  5. 并发问题排查工具:jstack(线程堆栈分析)、jconsole(线程监控)、Arthas(在线诊断)。

五、总结

Java 并发编程的核心是在保证线程安全的前提下,充分利用硬件资源提升性能。其底层依赖 JMM 解决可见性、原子性、有序性问题,上层通过线程、同步机制、线程池、并发工具类实现复杂并发场景。

学习并发编程的关键在于:

  • 理解底层原理(JMM、锁机制),而非死记 API;
  • 结合实战场景(如生产者 - 消费者、限流、任务同步),将技术落地;
  • 避开常见坑点(如 volatile 误用、死锁、线程池 OOM),写出稳健的代码。

建议开发者在日常开发中,从简单场景(如线程池使用、synchronized 同步)入手,逐步深入复杂场景(如并发工具类、异步编程),同时养成'用工具排查并发问题'的习惯(如 jstack 分析死锁),最终掌握并发编程这一核心技能。

目录

  1. 一、并发编程核心概念与底层原理
  2. 1. 为什么需要并发编程?
  3. 2. 核心概念辨析(避免混淆)
  4. 3. 底层原理:JVM 内存模型(JMM)
  5. 关键细节:
  6. 二、Java 并发编程核心技术拆解(含实战)
  7. 1. 线程创建与生命周期
  8. (1)三种创建方式(对比与选型)
  9. (2)线程生命周期(6 种状态)
  10. 关键避坑:
  11. 2. 同步机制:synchronized 与 Lock 详解
  12. (1)synchronized(隐式锁,JVM 层面实现)
  13. 实战示例:synchronized 解决 i++ 线程安全问题
  14. (2)Lock(显式锁,API 层面实现)
  15. 实战示例:ReentrantLock 实现生产者 - 消费者模型
  16. (3)synchronized 与 ReentrantLock 对比选型
  17. 3. 线程池:核心原理与参数优化
  18. (1)核心原理:ThreadPoolExecutor
  19. (2)任务执行流程(必记)
  20. (3)拒绝策略(4 种默认实现)
  21. (4)常见线程池(Executors 工具类)
  22. (5)生产环境线程池配置优化(实战)
  23. 实战配置示例:
  24. 4. 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
  25. (1)CountDownLatch(倒计时器)
  26. 实战场景:主线程等待 3 个任务线程执行完毕
  27. (2)CyclicBarrier(循环屏障)
  28. 实战场景:3 个线程同时开始执行任务
  29. (3)Semaphore(信号量)
  30. 实战场景:限制最多 2 个线程同时访问数据库连接
  31. 三、并发编程常见坑点与避坑指南
  32. 1. 坑点 1:volatile 关键字的误用
  33. 2. 坑点 2:线程池参数不合理导致 OOM
  34. 3. 坑点 3:死锁问题
  35. 4. 坑点 4:synchronized 锁范围过大导致性能问题
  36. 四、并发编程黄金法则(必记)
  37. 五、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Tecplot 360 EX2022 安装与使用指南
  • 3DMAX VR 渲染器局部渲染设置教程
  • IDEA 修改 Git 用户配置全流程
  • 大型语言模型高效提示工程(Prompt Engineering)实践指南
  • Java 数据类型、运算符和方法重点总结
  • Android 工程师面试准备指南:核心知识点与实战技巧
  • Spark 核心更新:Python UDF AST 转译与 K8s 突发内存感知机制
  • SpringBoot 整合 Zookeeper 常见错误总结
  • Windows 11 资源管理器增强插件 QTTabBar 中文优化版安装指南
  • 大模型技术原理及其在金融领域的应用分析
  • 为什么 Python 代码在函数中运行得更快
  • LeRobot 开源机器人学习框架入门指南
  • Java 性能优化的 50 个细节
  • OpenClaw 基础:Telegram 机器人配置与加入群聊
  • LLaMA-Factory 环境配置与 WebUI 启动指南:CUDA 适配与依赖解决
  • 技术副业变现路径:Python 爬虫开发实战指南
  • CentOS 7 yum 报错 Cannot find a valid baseurl 解决方案
  • 星辰 RPA 构建小红书自动发文机器人
  • 华为昇腾 910B 使用 LLaMA-Factory 微调 Qwen3.5-32B 模型指南
  • AI Agent 入门与 Coze 零代码搭建实战指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online