簡體   English   中英

沒有為 java 中的下一個線程清除 ThreadLocal 值

[英]ThreadLocal value not cleared for the next thread in java

我正在運行 web 服務,該服務至少接收 200 RPS。 基於該操作,我們為少數操作提供 root 訪問權限,並使用以下代碼。

private static final ThreadLocal<String> rootContext = new ThreadLocal<String>();

public Optional<String> getRunner() {
    if (rootContext.get() != null) {
        return rootContext.get();
    } else {
        return getCurrentRunner();
    }
}

public void rootAccess(Runnable runnable) {
    rootContext.set("root");
    runnable.run();
    rootContext.set(null);
}

getCurrentRunner()方法將根據請求返回實際的調用者。 問題是 200 個請求中有 1 個返回root而不是實際的調用者。

我注意到的一件事是,我沒有使用 threadlocal.remove(),而是將該值設置為 null。 預計 getRunner() rootContext.get() != null條件將失敗並返回實際的調用者。

如何解決這個問題? 設置rootContext.remove()會解決這個問題嗎? 如果是,如何?

謝謝您的幫助

您的rootAccess方法有兩個問題:

  1. 如果 Runnable 拋出 RuntimeException ThreadLocal 不會被刪除(可能是你所看到的)
  2. rootContext.set(null); 仍然保持與正在運行的線程關聯的ThreadLocal實例,最好做rootContext.remove();

更正這兩點意味着將rootAccess()更改為

public void rootAccess(Runnable runnable) {
    rootContext.set("root");
    try {
        runnable.run();
    } finally {
        rootContext.remove();
    }
}

為什么是rootContext.set(null); 一般有問題嗎?

每個線程基本上都保留一個類似於Map<ThreadLocal, ?>的數據結構,其中鍵是您的ThreadLocal實例( rootContext ),值是您通過rootContext.set(xx);

如果你調用rootContext.set(null); 那么rootContext仍然在 map 中,因此執行此行的每個線程(來自線程池,意味着線程長時間運行)都會保留對 rootContext 的引用,這反過來可能會阻止rootContext卸載。

如果你調用rootContext.remove(); rootContext 從rootContext中刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM