static final ThreadLocal
các biến là an toàn chủ đề.
static
làm cho biến ThreadLocal có sẵn trên nhiều lớp chỉ cho luồng tương ứng. đó là một loại phân tách biến Toàn cục của các biến cục bộ luồng tương ứng trên nhiều lớp.
Chúng ta có thể kiểm tra độ an toàn của luồng này với mẫu mã sau.
CurrentUser
- lưu trữ id người dùng hiện tại trong ThreadLocal
TestService
- Dịch vụ đơn giản với phương pháp - getUser()
để tìm nạp người dùng hiện tại từ CurrentUser.
TestThread
- lớp này được sử dụng để tạo nhiều luồng và thiết lập đồng thời các mã sử dụng
.
public class CurrentUser
public class CurrentUser {
private static final ThreadLocal<String> CURRENT = new ThreadLocal<String>();
public static ThreadLocal<String> getCurrent() {
return CURRENT;
}
public static void setCurrent(String user) {
CURRENT.set(user);
}
}
public class TestService {
public String getUser() {
return CurrentUser.getCurrent().get();
}
}
.
import java.util.ArrayList;
import java.util.List;
public class TestThread {
public static void main(String[] args) {
List<Integer> integerList = new ArrayList<>();
//creates a List of 100 integers
for (int i = 0; i < 100; i++) {
integerList.add(i);
}
//parallel stream to test concurrent thread execution
integerList.parallelStream().forEach(intValue -> {
//All concurrent thread will set the user as "intValue"
CurrentUser.setCurrent("" + intValue);
//Thread creates a sample instance for TestService class
TestService testService = new TestService();
//Print the respective thread name along with "intValue" value and current user.
System.out.println("Start-"+Thread.currentThread().getName()+"->"+intValue + "->" + testService.getUser());
try {
//all concurrent thread will wait for 3 seconds
Thread.sleep(3000l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Print the respective thread name along with "intValue" value and current user.
System.out.println("End-"+Thread.currentThread().getName()+"->"+intValue + "->" + testService.getUser());
});
}
}
.
Chạy lớp chính TestThread. Đầu ra -
Start-main->62->62
Start-ForkJoinPool.commonPool-worker-2->31->31
Start-ForkJoinPool.commonPool-worker-3->81->81
Start-ForkJoinPool.commonPool-worker-1->87->87
End-main->62->62
End-ForkJoinPool.commonPool-worker-1->87->87
End-ForkJoinPool.commonPool-worker-2->31->31
End-ForkJoinPool.commonPool-worker-3->81->81
Start-ForkJoinPool.commonPool-worker-2->32->32
Start-ForkJoinPool.commonPool-worker-3->82->82
Start-ForkJoinPool.commonPool-worker-1->88->88
Start-main->63->63
End-ForkJoinPool.commonPool-worker-1->88->88
End-main->63->63
...
Tóm tắt phân tích
- luồng "chính" bắt đầu và đặt người dùng hiện tại là "62", song song luồng "ForkJoinPool.commonPool-worker-2" bắt đầu và đặt người dùng hiện tại là "31", song song đó luồng "ForkJoinPool.commonPool-worker-3" bắt đầu và đặt hiện tại người dùng là "81", song song với chuỗi "ForkJoinPool.commonPool-worker-1" bắt đầu và đặt người dùng hiện tại là "87" Start-main-> 62-> 62 Start-ForkJoinPool.commonPool-worker-2-> 31-> 31 Start-ForkJoinPool.commonPool-worker-3-> 81-> 81 Start-ForkJoinPool.commonPool-worker-1-> 87-> 87
- Tất cả các chuỗi trên sẽ ngủ trong 3 giây
main
thực thi kết thúc và in người dùng hiện tại là "62", ForkJoinPool.commonPool-worker-1
thực thi song song kết thúc và in người dùng hiện tại là "87", ForkJoinPool.commonPool-worker-2
thực thi song song kết thúc và in người dùng hiện tại là "31", ForkJoinPool.commonPool-worker-3
thực thi song song kết thúc và in người dùng hiện tại là "81"
Sự suy luận
Các luồng đồng thời có thể truy xuất các mã sử dụng chính xác ngay cả khi nó đã được khai báo là "static final ThreadLocal"