Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

线程池中出现数据丢失或数据重用的情况 #349

Closed
HuangDayu opened this issue Jan 8, 2022 · 2 comments
Closed

线程池中出现数据丢失或数据重用的情况 #349

HuangDayu opened this issue Jan 8, 2022 · 2 comments
Assignees
Labels
💪 enhancement ❓question Further information is requested

Comments

@HuangDayu
Copy link

HuangDayu commented Jan 8, 2022

你好,使用场景是这样的。业务上存在一个或者多个线程池,每一个线程池的任务会创建新的线程任务,任务可能是跨线程池的,也可能是在同一个线程池中。问题是出现了数据丢失或者旧数据重用的情况,在任务多的情况下出现的更加频繁。

public class TTLTest {

    static TransmittableThreadLocal<String> transmittableThreadLocal = new TransmittableThreadLocal<>();
    static Executor executorService1;

    @Before
    public void init() {
        executorService1 = eventBusExecutor();
        TtlExecutors.getTtlExecutor(executorService1);
    }

    @Test
    public void run() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            transmittableThreadLocal.set(i + " - " + UUID.randomUUID().toString());
            execute1();
            System.out.println();
            TimeUnit.MILLISECONDS.sleep(2);
        }
    }


    public void execute1() {
        executorService1.execute(() -> {
            System.out.println("execute1 -> " + transmittableThreadLocal.get());
            execute2();
            try {
                TimeUnit.MILLISECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }

    public void execute2() {
        executorService1.execute(() -> {
            System.out.println("execute2 -> " + transmittableThreadLocal.get());
        });
    }


    public Executor eventBusExecutor() {
        int processors = Runtime.getRuntime().availableProcessors();
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(processors);
        executor.setMaxPoolSize(processors * 4);
        executor.setQueueCapacity(processors * 8);
        executor.setThreadNamePrefix("Context-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

}

这个输出结果:

execute1 -> 0 - f424790a-3695-46be-8fa9-bebb4adbe257
execute2 -> 0 - f424790a-3695-46be-8fa9-bebb4adbe257

execute1 -> 1 - 73e441f2-8e96-4dac-af82-f2ffec92b363
execute2 -> 1 - 73e441f2-8e96-4dac-af82-f2ffec92b363

execute1 -> 2 - dc092e47-e14d-458a-b52c-8ac275adcd9b
execute2 -> 2 - dc092e47-e14d-458a-b52c-8ac275adcd9b

execute1 -> 3 - 80700d0d-5c27-45de-a9e2-8a182e1fabf1
execute2 -> 3 - 80700d0d-5c27-45de-a9e2-8a182e1fabf1

execute1 -> 4 - 4b1ebbc9-88da-47ad-87a9-442f2f046b17
execute2 -> 4 - 4b1ebbc9-88da-47ad-87a9-442f2f046b17

execute1 -> 5 - 4bbc084d-0d60-4471-b5f5-e374cbdc1f1c
execute2 -> 5 - 4bbc084d-0d60-4471-b5f5-e374cbdc1f1c

execute1 -> 6 - 0d289dd2-6cd7-4c74-8e3a-747b058ab11b
execute2 -> 6 - 0d289dd2-6cd7-4c74-8e3a-747b058ab11b

execute1 -> 7 - 2f46b88a-9d42-4b07-bc66-e0f9e59811b1
execute2 -> 7 - 2f46b88a-9d42-4b07-bc66-e0f9e59811b1

execute1 -> 0 - f424790a-3695-46be-8fa9-bebb4adbe257
execute2 -> 0 - f424790a-3695-46be-8fa9-bebb4adbe257

execute1 -> 1 - 73e441f2-8e96-4dac-af82-f2ffec92b363
execute2 -> 1 - 73e441f2-8e96-4dac-af82-f2ffec92b363

可以看到,第0次和第1次的数据被重用了,而第8次和第9次的数据则丢失了。

execute1 -> 0 - feaf48cc-b69a-45a9-8fe0-1cb6a1f011fc
execute2 -> 0 - feaf48cc-b69a-45a9-8fe0-1cb6a1f011fc

execute1 -> 1 - be5d923a-a8df-4637-9401-920f48fea82d
execute2 -> 1 - be5d923a-a8df-4637-9401-920f48fea82d

execute1 -> 2 - a61872d1-abc1-4d69-9c93-dd108486642d
execute2 -> 2 - a61872d1-abc1-4d69-9c93-dd108486642d

execute1 -> 3 - f208f099-3a42-4d68-9672-bd22f183564a
execute2 -> 3 - f208f099-3a42-4d68-9672-bd22f183564a

execute1 -> 4 - c09511ad-ab35-4c2a-a83d-f5021c9ec48d
execute2 -> 4 - c09511ad-ab35-4c2a-a83d-f5021c9ec48d

execute1 -> 5 - 85e05522-5685-46e0-9163-26129e4ca262
execute2 -> 5 - 85e05522-5685-46e0-9163-26129e4ca262

execute1 -> 6 - a0c5e2c5-a28e-49b1-ac51-4209f7138423
execute2 -> 6 - a0c5e2c5-a28e-49b1-ac51-4209f7138423

execute1 -> 7 - ecb16d9f-34db-47ca-9d9d-bd0f39872150
execute2 -> 7 - ecb16d9f-34db-47ca-9d9d-bd0f39872150

execute1 -> 0 - feaf48cc-b69a-45a9-8fe0-1cb6a1f011fc
execute2 -> 1 - be5d923a-a8df-4637-9401-920f48fea82d

execute1 -> 0 - feaf48cc-b69a-45a9-8fe0-1cb6a1f011fc
execute2 -> 1 - be5d923a-a8df-4637-9401-920f48fea82d

这一次结果也可以看到,第0次和第1次的数据交叉重用,而第8次和第9次的数据也丢失了。

这似乎是一个必现的问题,是不是我没有手动remove的问题,还是使用的方式存在问题,请赐教,谢谢。

@HuangDayu
Copy link
Author

找到了问题的原因,在于没有使用装饰后的线程池对象,而是使用了旧的对象。

    @Before
    public void init() {

        //executorService1 = eventBusExecutor();
        //TtlExecutors.getTtlExecutor(executorService1);

        executorService1 = TtlExecutors.getTtlExecutor(eventBusExecutor());
    }

建议在文档中显著表明一下。:wink:

@oldratlee oldratlee added the ❓question Further information is requested label Jan 8, 2022
@oldratlee oldratlee self-assigned this Jan 8, 2022
oldratlee added a commit that referenced this issue Jun 30, 2022
…iendly:

trigger `IDE` warning if discard `wrapper` result #349
@oldratlee
Copy link
Member

oldratlee commented Jun 30, 2022

找到了问题的原因,在于没有使用装饰后的线程池对象,而是使用了旧的对象。

    @Before
    public void init() {

        //executorService1 = eventBusExecutor();
        //TtlExecutors.getTtlExecutor(executorService1);

        executorService1 = TtlExecutors.getTtlExecutor(eventBusExecutor());
    }

建议在文档中显著表明一下。😉

@HuangDayu 加了一个代码优化: a545558,发布在 v2.13.2
https://github.com/alibaba/transmittable-thread-local/releases/tag/v2.13.2

上面错误的使用方式,在IntelliJ IDEA中,会有警告出来:✅ 😋

image

之前的TTL版本,IntelliJ IDEA并不能有警告提示:❌ 😖

image

oldratlee added a commit that referenced this issue Jul 1, 2022
…iendly:

trigger `IDE` warning if discard `wrapper` result #349
oldratlee added a commit that referenced this issue Jul 1, 2022
…iendly:

trigger `IDE` warning if discard `wrapper` result #349
oldratlee added a commit that referenced this issue Jul 4, 2022
…iendly:

trigger `IDE` warning if discard `wrapper` result #349
oldratlee added a commit that referenced this issue Jul 4, 2022
…iendly:

trigger `IDE` warning if discard `wrapper` result #349
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💪 enhancement ❓question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants