ThreadLocal sẽ đảm bảo truy cập đối tượng có thể thay đổi bởi nhiều luồng trong phương thức không đồng bộ được đồng bộ hóa, có nghĩa là làm cho đối tượng có thể thay đổi trở thành bất biến trong phương thức.
Điều này đạt được bằng cách đưa ra phiên bản mới của đối tượng có thể thay đổi cho mỗi luồng thử truy cập vào nó. Vì vậy, nó là bản sao cục bộ cho mỗi chủ đề. Đây là một số hack về việc tạo biến thể hiện trong một phương thức được truy cập như một biến cục bộ. Như bạn biết phương thức biến cục bộ chỉ có sẵn cho luồng, một điểm khác biệt là; các biến cục bộ của phương thức sẽ không có sẵn cho luồng khi quá trình thực thi phương thức kết thúc khi đối tượng có thể thay đổi được chia sẻ với luồng sẽ có sẵn trên nhiều phương thức cho đến khi chúng ta dọn sạch nó.
Theo định nghĩa:
Lớp ThreadLocal trong Java cho phép bạn tạo các biến chỉ có thể được đọc và ghi bởi cùng một luồng. Do đó, ngay cả khi hai luồng đang thực thi cùng một mã và mã có tham chiếu đến biến ThreadLocal, thì hai luồng không thể nhìn thấy các biến ThreadLocal của nhau.
Mỗi Thread
trong java chứa ThreadLocalMap
trong đó.
Ở đâu
Key = One ThreadLocal object shared across threads.
value = Mutable object which has to be used synchronously, this will be instantiated for each thread.
Đạt được ThreadLocal:
Bây giờ hãy tạo một lớp bao bọc cho ThreadLocal sẽ giữ đối tượng có thể thay đổi như bên dưới (có hoặc không có initialValue()
).
Bây giờ getter và setter của trình bao bọc này sẽ hoạt động trên thể hiện luồng thay vì đối tượng có thể thay đổi.
Nếu getter () của threadlocal không tìm thấy bất kỳ giá trị nào trong sơ đồ luồng của Thread
; sau đó nó sẽ gọi initValue () để lấy bản sao riêng của nó đối với luồng.
class SimpleDateFormatInstancePerThread {
private static final ThreadLocal<SimpleDateFormat> dateFormatHolder = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd") {
UUID id = UUID.randomUUID();
@Override
public String toString() {
return id.toString();
};
};
System.out.println("Creating SimpleDateFormat instance " + dateFormat +" for Thread : " + Thread.currentThread().getName());
return dateFormat;
}
};
/*
* Every time there is a call for DateFormat, ThreadLocal will return calling
* Thread's copy of SimpleDateFormat
*/
public static DateFormat getDateFormatter() {
return dateFormatHolder.get();
}
public static void cleanup() {
dateFormatHolder.remove();
}
}
Bây giờ wrapper.getDateFormatter()
sẽ gọi threadlocal.get()
và điều đó sẽ kiểm tra currentThread.threadLocalMap
chứa này (ThreadLocal) ví dụ.
Nếu có trả về giá trị (SimpleDateFormat) cho thể hiện luồng tương ứng
khác, hãy thêm bản đồ với đối tượng luồng này, initValue ().
Dưới đây là an toàn chủ đề đạt được trên lớp đột biến này; bởi mỗi luồng đang làm việc với thể hiện có thể thay đổi của chính nó nhưng với cùng thể hiện ThreadLocal. Có nghĩa là Tất cả các luồng sẽ chia sẻ cùng một đối tượng ThreadLocal như khóa, nhưng đối tượng SimpleDateFormat khác nhau làm giá trị.
https://github.com/skanagavelu/yt.tech/blob/master/src/ThreadLocalTest.java