netty-FastThreadLocal用法测试

本文通过一个测试例子,对比了Netty中FastThreadLocal与标准ThreadLocal的性能。测试结果显示,在大量并发请求和多次调用get方法的情况下,FastThreadLocal表现出更好的性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


2017年写Netty相关文章的时候,关于Netty中FastThreadLocal.java源码解读的文章还很少。今天(2019-02-25)回头过来整理的时候,发现网上已经涌现出了许多篇介绍FastThreadLocal.java的文章,并且,已经有解读的比较详实的文章,所以本人已经不打算进一步分析源码了。此处暂且列出几篇优秀的博文供大家查阅。
1. Netty精粹之设计更快的ThreadLocal
2. Netty学习之旅----ThreadLocal原理分析与性能优化思考(思考篇)

下文将给出一个测试例子,用于比较ThreadLocal与FastThreadLocal的性能。

import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.concurrent.FastThreadLocalThread;
import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

public class FastThreadLocalTest {

    /**
     * 测试ThreadLocal运行耗时
     *
     * @param threadLocalCount ThreadLocal的对象数量
     * @param runCount         调用get方法的次数
     * @param value            ThreadLocal的局部变量值
     * @return
     * @author lihong10 2019/2/25 19:19
     * @modificationHistory=========================逻辑或功能性重大变更记录
     * @modify by user: {修改人} 2019/2/25 19:19
     * @modify by reason:{原因}
     */
    public static void testThreadLocal(int threadLocalCount, int runCount, String value) {
        final ThreadLocal<String>[] caches = new ThreadLocal[threadLocalCount];
        final Thread mainThread = Thread.currentThread();
        for (int i = 0; i < threadLocalCount; i++) {
            caches[i] = new ThreadLocal();
        }
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < threadLocalCount; i++) {
                    caches[i].set(value);
                }
                long start = System.nanoTime();
                for (int i = 0; i < threadLocalCount; i++) {
                    for (int j = 0; j < runCount; j++) {
                        caches[i].get();
                    }
                }
                long end = System.nanoTime();
                System.out.println(" thread local take[" + TimeUnit.NANOSECONDS.toMillis(end - start) +
                        "]ms");
                LockSupport.unpark(mainThread);
            }

        });
        t.start();
        LockSupport.park(mainThread);
    }


    /**
     * 测试FastThreadLocal运行耗时
     *
     * @param threadLocalCount FastThreadLocal的对象数量
     * @param runCount         调用get方法的次数
     * @param value            FastThreadLocal的局部变量值
     * @return
     * @author lihong10 2019/2/25 19:19
     * @modificationHistory=========================逻辑或功能性重大变更记录
     * @modify by user: {修改人} 2019/2/25 19:19
     * @modify by reason:{原因}
     */
    public static void testFastThreadLocal(int threadLocalCount, int runCount, String value) {
        final FastThreadLocal<String>[] caches = new FastThreadLocal[threadLocalCount];
        final Thread mainThread = Thread.currentThread();
        for (int i = 0; i < threadLocalCount; i++) {
            caches[i] = new FastThreadLocal();
        }
        Thread t = new FastThreadLocalThread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < threadLocalCount; i++) {
                    caches[i].set(value);
                }
                long start = System.nanoTime();
                for (int i = 0; i < threadLocalCount; i++) {
                    for (int j = 0; j < runCount; j++) {
                        caches[i].get();
                    }
                }
                long end = System.nanoTime();
                System.out.println("fast thread local take[" + TimeUnit.NANOSECONDS.toMillis(end - start) +
                        "]ms");
                LockSupport.unpark(mainThread);
            }

        });
        t.start();
        LockSupport.park(mainThread);
    }


    /**
     * 对比ThreadLocal和 FastThreadLocal的耗时
     * @author lihong10 2019/2/25 19:25
     * @param
     * @return
     * @modificationHistory=========================逻辑或功能性重大变更记录
     * @modify by user: {修改人} 2019/2/25 19:25
     * @modify by reason:{原因}
     */
    @Test
    public void test() {
        String value = "thread local value";
        testThreadLocal(1000, 1000000, value);
        testFastThreadLocal(1000, 1000000, value);
    }


}

<think>我们正在讨论Netty中的两个依赖概念:netty-bom和netty-all。它们的作用和区别是什么? 根据引用[1]和引用[3]: 引用[1]提到Reactor Netty的文档中介绍了使用BOM(Bill of Materials)来管理依赖版本,这有助于统一管理Netty相关组件的版本。 引用[3]则提到了一个构建错误,涉及无法解析netty-bom的特定版本(4.1.33.Final),这说明了项目中可能使用了BOM。 另外,引用[4]提到了在导入Netty代码时遇到的依赖问题,其中包含了Spring Boot的依赖,但并没有直接提到netty-all。 现在,我们分析两个依赖: 1. netty-bom (Bill of Materials) - BOM是一个特殊的POM文件,它定义了所有相关模块的版本。在Maven或Gradle中引入BOM后,可以避免在添加各个Netty模块依赖时指定版本,从而保证版本的一致性。 - 例如,在Maven中,我们可以这样引入BOM: ```xml <dependencyManagement> <dependencies> <dependency> <groupId>io.netty</groupId> <artifactId>netty-bom</artifactId> <version>4.1.86.Final</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ``` - 然后,在添加具体的Netty模块(如netty-buffer, netty-transport等)时,就不需要指定版本了,因为它们会使用BOM中定义的版本。 2. netty-all - 这是一个“超级”jar,它包含了所有Netty模块的代码。也就是说,如果你引入了netty-all,就相当于一次性引入了Netty的所有功能模块(如核心、编解码、传输层等)。 - 在Maven中引入方式如下: ```xml <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.86.Final</version> </dependency> ``` 区别总结: - **作用不同**:netty-bom用于依赖管理,统一版本;netty-all是一个聚合依赖,包含了所有Netty模块的类。 - **使用方式不同**:netty-bom需要在`<dependencyManagement>`中引入,而netty-all则作为普通依赖引入。 - **体积不同**:netty-all会包含所有模块的代码,因此体积较大;而netty-bom本身不包含代码,只是一个版本管理的POM文件,所以非常小。 - **适用场景**: - 使用netty-bom:当项目需要多个Netty模块,并且希望这些模块的版本保持一致,同时希望按需引入具体模块(避免引入不必要的代码)时。 - 使用netty-all:当项目需要用到Netty的多个模块,并且不介意引入整个Netty库(即不关心体积大小)时,或者为了简化配置(只需一个依赖)时。 注意事项: - 在大型项目中,通常推荐使用BOM来管理版本,然后按需引入具体模块,这样可以减少最终打包的体积(只包含实际用到的模块)。 -netty-all虽然方便,但可能会引入很多未使用的模块,导致应用体积增大。 因此,根据项目需求选择: - 如果需要精细控制依赖,使用netty-bom。 - 如果为了快速启动或测试,且不介意体积,可以使用netty-all。 另外,引用[2]提到了Netty的跨平台等特性,这些特性无论使用哪种依赖管理方式都是具备的。 引用[5]中提到的BOM(Byte Order Mark)与这里的Bill of Materials不同,是另一个概念。 综上,我们清晰地区分了netty-bom和netty-all。</think>### Netty BOM 与 Netty All 依赖的区别 #### 1. **核心功能差异** - **Netty BOM (Bill of Materials)** 本质是一个**版本管理工具**,不包含任何代码实现。它通过统一声明所有 Netty 子模块的版本号(如 `netty-buffer`, `netty-transport` 等),确保项目中多个 Netty 依赖的版本一致性[^1][^3]。 **作用**:解决 Maven/Gradle 项目中因版本冲突导致的构建错误(如引用[3]中的 `Non-resolvable import POM` 错误)。 - **Netty All** 是一个**聚合依赖包**,包含 Netty 框架的所有核心模块代码(如编解码、传输层、缓冲区等)。引入后相当于一次性导入整个 Netty 库[^2]。 #### 2. **使用场景对比** | **场景** | **Netty BOM** | **Netty All** | |------------------------|------------------------------------------|------------------------------------| | **依赖管理** | 统一管理版本,避免冲突(推荐大型项目)[^1] | 无版本管理功能 | | **代码体积** | 仅版本声明文件(几KB) | 包含全部代码(约4-5MB) | | **适用项目** | 多模块项目、微服务架构 | 快速原型开发、小型应用 | | **灵活性** | 可自由选择需要的子模块 | 强制引入所有模块,无法按需加载 | #### 3. **配置示例** **Netty BOM 配置 (Maven)** ```xml <dependencyManagement> <dependencies> <dependency> <groupId>io.netty</groupId> <artifactId>netty-bom</artifactId> <version>4.1.100.Final</version> <!-- 统一版本 --> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 按需引入子模块(无需指定版本) --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-buffer</artifactId> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-transport</artifactId> </dependency> ``` **Netty All 配置** ```xml <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.100.Final</version> <!-- 需显式指定版本 --> </dependency> ``` #### 4. **典型问题分析** - **Netty BOM 未生效** 如引用[3]所示,通常是仓库未同步或版本号错误导致,需检查: 1. 仓库配置(如 Nexus 地址) 2. 版本号是否存在(如 `4.1.33.Final`) 3. 是否遗漏 `<type>pom</type>` 和 `<scope>import</scope>` - **Netty All 的缺陷** - 冗余依赖:可能引入未使用的模块(如 HTTP/2 支持) - 升级困难:更新版本需全局替换,易引发兼容性问题 - 依赖冲突:与其他库(如 gRPC)共用时易出现类加载错误[^4] #### 5. **最佳实践建议** 1. **生产环境优先用 BOM** 通过精细控制依赖(如仅引入 `netty-transport-native-epoll`)减少包体积[^1][^2]。 2. **Netty All 仅限临时场景** 适合快速验证功能,但上线前应切换为 BOM + 按需引入。 3. **版本同步技巧** Spring Boot 项目可通过 `spring-boot-dependencies` 自动管理 Netty 版本[^4]。 > 💡 引用[2]提到 Netty 的跨平台特性:BOM 可确保不同平台(Linux/Windows)依赖的 native 模块版本一致,避免运行时异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值