static final ThreadLocal
değişkenler iş parçacığı açısından güvenlidir.
static
ThreadLocal değişkenini yalnızca ilgili iş parçacığı için birden çok sınıfta kullanılabilir hale getirir. bu, birden çok sınıfta ilgili iş parçacığı yerel değişkenlerinin bir tür Global değişken tanımlamasıdır.
Bu iş parçacığı güvenliğini aşağıdaki kod örneği ile kontrol edebiliriz.
CurrentUser
- mevcut kullanıcı kimliğini ThreadLocal'da saklar
TestService
- Yöntemle basit hizmet - getUser()
mevcut kullanıcıyı CurrentUser'dan almak için.
TestThread
- bu sınıf, birden çok iş parçacığı oluşturmak ve aynı anda kullanıcı kimliklerini ayarlamak için kullanılır
.
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());
});
}
}
.
TestThread ana sınıfını çalıştırın. Çıktı -
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
...
Analiz özeti
- "ana" iş parçacığı başlar ve geçerli kullanıcıyı "62" olarak ayarlar, paralel olarak "ForkJoinPool.commonPool-işçi-2" iş parçacığı başlar ve mevcut kullanıcıyı "31" olarak ayarlar, paralel olarak "ForkJoinPool.commonPool-işçi-3" iş parçacığı başlar ve akımı ayarlar kullanıcı "81" olarak, paralel olarak "ForkJoinPool.commonPool-işçi-1" iş parçacığı başlar ve mevcut kullanıcıyı "87" Başlatma-ana-> 62-> 62 Start-ForkJoinPool.commonPool-işçi-2-> 31-> 31 olarak ayarlar Start-ForkJoinPool.commonPool-worker-3-> 81-> 81 Start-ForkJoinPool.commonPool-worker-1-> 87-> 87
- Yukarıdaki konuların tümü 3 saniye uyuyacak
main
yürütme sona erer ve geçerli kullanıcıyı "62" olarak yazdırır, paralel olarak ForkJoinPool.commonPool-worker-1
yürütme sona erer ve mevcut kullanıcıyı "87" olarak yazdırır, paralel olarak ForkJoinPool.commonPool-worker-2
yürütme sona erer ve mevcut kullanıcıyı "31" olarak yazdırır, paralel olarak ForkJoinPool.commonPool-worker-3
yürütme sona erer ve mevcut kullanıcıyı "81" olarak yazdırır
Çıkarım
Concurrent Threads, "statik final ThreadLocal" olarak bildirilmiş olsa bile doğru kullanıcı kimliklerini alabilir.