为什么ThreadLocal不在新线程中创建?

时间:2019-03-22 13:22:10

标签: java multithreading thread-safety

创建了类Collector以生成具有值的地图(例如)。 需要收集器包含资源,该资源只能由当前线程访问。

下面显示了类Collector:

    Sub loop_test()

Dim i As Integer
Dim ws_num As Integer

Dim starting_ws As Worksheet
Set starting_ws = ActiveSheet
ws_num = ThisWorkbook.Worksheets.Count

For i = 1 To ws_num
    ThisWorkbook.Worksheets(i).Activate
    '
    Dim lastrow As Long
Dim LastColumn As Long
Dim StartCell As Range
Set StartCell = Range("A1")


  lastrow = Cells(Rows.Count, StartCell.Column).End(xlUp).Row
  Range(StartCell, Cells(lastrow, LastColumn)).Select

  Dim objTable As ListObject
Set objTable = ActiveSheet.ListObjects.Add(xlSrcRange, Selection, , xlYes)



Next

starting_ws.Activate
End Sub

我尝试在不同的线程中同时执行方法public class Collector { ThreadLocal<Map<String, String>> storage; public Map<String, String> collection(int id) { storage = new ThreadLocal<>(); storage.set(new HashMap<>()); for (int i = id * 100; i <= id * 1000; i+=id * 100) { storage.get().put(String.valueOf(i), "test"); } return storage.get(); } } 。我的建议基于the official documentation。但是有时会抛出 NullPointerException ,我的观察结果指出了另一个线程重新创建ThreadLocal的情况,所以 NullPointerException 抛出了collection(int id),因为在另一个线程中行storage.get().put(String.valueOf(i), "test");已重新初始化。

下面显示的代码中,运行两个线程:

storage = new ThreadLocal<>();

我如何使用ThreadLocal在每个线程中拥有本地资源,这与另一个线程无关?

1 个答案:

答案 0 :(得分:2)

问题是您每次重新创建新的ThreadLocal实例

collection(int)

方法被调用,

this.storage = new ThreadLocal<>();

ThreadLocal<Map<String, String>>可以是类static的字段

private final static ThreadLocal<Map<String, String>> STORAGE = new ThreadLocal<>();

要设置并获取Thread的关联值,只需使用

// You're better off passing and using an already constructed instance
STORAGE.set(new HashMap<>());
STORAGE.get();