6 Nisan 2023 Perşembe

ScopedValues Sınıfı - ThreadLocal Gibidir

Giriş
Açıklaması şöyle
Introducing Scoped Values, which enable sharing immutable data within and between threads. They are preferred over thread-local variables, especially when using a large number of virtual threads.
Project Loom ile gelen Virtual Thread'lerden önce ThreadLocal kullanılıyordu. Örneğin şöyle yaparız
class Handler {
  final static ThreadLocal<String> userInfo = new ThreadLocal<>();
  ...
}

userInfo.set("user-name");
....
Handler.userInfo.get();
ThreadLocal bazı aleyhte durumlara sahip
1. Mutability
ThreadLocal#get() ve ThreadLocal#set() ile değiştirilebilir

2. Unbounded Lifetime
ThreadLocal nesnesi, thread yaşadığı müddetçe hayattadır. Eğer erken silmek istersek ThreadLocal#remove() çağrısı yapılır

3. Overhead in Virtual Threads
Açıklaması şöyle. Yani Project Loom ile gelen Virtual Thread'lerde ThreadLocal kullanmak mümkün ama yapmasak daha iyi. Bunun yerine artık ScopedValue geldi.
Virtual threads are still Threads, though. That means they can use ThreadLocal<T>, but now, the previously mentioned downsides affect your program at another scale. If you think the overhead or lifetime issues and coordination of a few ThreadLocal<T> are problematic when handling a handful of threads, you better don’t think about these downsides when handling 10.000+ virtual threads!
newInstance metodu
Örnek
Şöyle yaparız
private static final ThreadLocal<Principal> PRINCIPAL_TL = new ThreadLocal();

// - VS -
private static final ScopedValue<Principal> PRINCIPAL_SV = ScopedValue.newInstance();
where metodu
İmzası şöyle
<T> ScopedValue.Carrier where(ScopedValue<T> key, T value)
ScopedValue.Carrier nesnesin Runnable veya Callable takılabiliyor. İmzası şöyle
void run(Runnable op)
<R> R call(Callable<? extends R> op)
Örnek
Şöyle yaparız
private static final ScopedValue<String> USER = ScopedValue.newInstance();

ScopedValue.Carrier carrier = ScopedValue.where(USER, "ben");

var boundUser = carrier.get(USER);
// => "ben"

carrier.run(() -> {
    var currentUser = USER.get();
    // => "ben"
});
Örnek
Şöyle yaparız
private static final ScopedValue<String> USER = ScopedValue.newInstance();

// CREATE TWO CARRIERS WITH DIFFERENT VALUES IN THE SAME THREAD

ScopedValue.Carrier carrierForBen = ScopedValue.where(USER, "ben");
ScopedValue.Carrier carrierForBob = ScopedValue.where(USER, "bob");

// USE THE SAME RUNNABLE FOR EACH CARRIER

Runnable r = () -> {
    var currentUser = USER.get();
    System.out.println("Current: " + currentUser);
};

// RUN RUNNABLE WITH DIFFERENT CARRIERS

carrierForBen.run(r);
// => "Current: ben"

carrierForBob.run(r);
// => "Current: bob"

carrierForBen.run(r);
// => "Current: ben"


Hiç yorum yok:

Yorum Gönder