Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to solve the value passing problem of pooled Multiplex Thread by TransmittableThreadLocal

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces "TransmittableThreadLocal how to solve the value transfer problem of pooled reuse threads". In daily operation, I believe that many people have doubts about how to solve the value transfer problem of pooled reuse threads in TransmittableThreadLocal. I have consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts of "how to solve the value transfer problem of pooled reuse threads by TransmittableThreadLocal". Next, please follow the editor to study!

TransmittableThreadLocal

In general, ThreadLocal can meet our needs when we need to pass ThreadLocal when we need to use execution components such as thread pools that will pool and reuse threads

This scenario is the problem that TransmittableThreadLocal solves.

Github address: https://github.com/alibaba/transmittable-thread-local

If you are interested, you can download it and play it. Next, let's introduce the magic of this component.

First of all, let's take a look at demo. Through demo, we first learn how to use it.

Demo/** * ttl Test * * @ author zhangyunhe * @ date 2020-04-23 12:47 * / public class Test {/ / 1. Initialize a TransmittableThreadLocal, which inherits InheritableThreadLocal's static TransmittableThreadLocal local = new TransmittableThreadLocal (); / / initializes a thread pool of length 1 static ExecutorService poolExecutor = Executors.newFixedThreadPool (1); public static void main (String [] args) throws ExecutionException, InterruptedException {Test test = new Test (); test.test () } private void test () throws ExecutionException, InterruptedException {/ / set the initial value local.set ("Heavenly King Laozi"); / /! Note: the Task in this place is Future future = poolExecutor.submit (TtlRunnable.get (new Task ("Task 1")); future.get (); Future future2 = poolExecutor.submit (TtlRunnable.get (new Task ("Task 2")); future2.get (); System.out.println ("value of parent thread:" + local.get ()); poolExecutor.shutdown () " } class Task implements Runnable {String str; Task (String str) {this.str = str;} @ Override public void run () {/ / get the value System.out.println (Thread.currentThread (). GetName () + ":" + local.get ()); / / reset a wave of local.set (str) }}}

Output result:

Pool-1-thread-1: heavenly King Laozi pool-1-thread-1: the value of Heavenly King Laozi Father Thread: an Analysis of the principle of Heavenly King Laozi

Let's first take a look at the source code of TransmittableThreadLocal

Public class TransmittableThreadLocal extends InheritableThreadLocal implements TtlCopier {/ / 1. Holder here is his main design point, followed by building TtlRunnable private static InheritableThreadLocal holder = new InheritableThreadLocal () {@ Override protected WeakHashMap initialValue () {return new WeakHashMap ();} @ Override protected WeakHashMap childValue (WeakHashMap parentValue) {return new WeakHashMap (parentValue) }}; @ SuppressWarnings ("unchecked") private void addThisToHolder () {if (! holder.get (). ContainsKey (this)) {holder.get (). Put ((TransmittableThreadLocal) this, null); / / WeakHashMap supports null value. } @ Override public final T get () {T value = super.get (); if (disableIgnoreNullValueSemantics | | null! = value) addThisToHolder (); return value } / * see {@ link InheritableThreadLocal#set} * / @ Override public final void set (T value) {if (! disableIgnoreNullValueSemantics & & null = = value) {/ / may set null to remove value remove ();} else {super.set (value); addThisToHolder () }} / * * see {@ link InheritableThreadLocal#remove ()} * / @ Override public final void remove () {removeThisFromHolder (); super.remove ();} private void superRemove () {super.remove ();}}

Step instructions:

In the code, the author constructs a holder object, which is an InheritableThreadLocal, in which the type is a weakly referenced WeakHashMap, the valu of this map is TransmittableThreadLocal, and the value is always empty

What is stored in holder is all the references to TransmittableThreadLocal in this application.

As you can see from above, every time get, set, and remove manipulate the holder object, the purpose of this is to keep all the references of the TransmittableThreadLocal stored in the holder.

TtlRunnable

Go back to our code above.

Future future = poolExecutor.submit (TtlRunnable.get (new Task (Task 1)

Careful friends may have found out that we have called the get method of the TtlRunnable object. Let's see what this method does.

Public static TtlRunnable get (@ Nullable Runnable runnable, boolean releaseTtlValueReferenceAfterRun, boolean idempotent) {if (null = = runnable) return null; if (runnable instanceof TtlEnhanced) {/ / avoid redundant decoration, and ensure idempotency if (idempotent) return (TtlRunnable) runnable; else throw new IllegalStateException ("Already TtlRunnable!");} / / focus on return new TtlRunnable (runnable, releaseTtlValueReferenceAfterRun);}

Look at the above code, we do not look at the details, we look at the general idea, this place is mainly based on the incoming runnable to build a TtlRunnable object.

Private TtlRunnable (@ NonNull Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {/ / focus on here this.capturedRef = new AtomicReference (capture ()); this.runnable = runnable; this.releaseTtlValueReferenceAfterRun = releaseTtlValueReferenceAfterRun;}

The following line of code, when running here, is still in the main thread, calling the capture method

This.capturedRef = new AtomicReference (capture ()); capturepublic static Object capture () {/ / build a temporary object, depending on the captureTtlValues method return new Snapshot (captureTtlValues (), captureThreadLocalValues ());} private static WeakHashMap captureTtlValues () {/ / build a WeakHashMap method, WeakHashMap ttl2Value = new WeakHashMap () / / in the main thread, call the holder variable and loop to get all the key and value for (TransmittableThreadLocal threadLocal: holder.get (). KeySet ()) {ttl2Value.put (threadLocal, threadLocal.copyValue ());} / return out return ttl2Value;}

Step instructions:

1. Call the static variable holder and loop to get all the key and value in it, and the acquisition of value is more ingenious.

Private T copyValue () {/ / the get method here calls the method of the parent class, and you can finally get the value return copy (get ()) corresponding to the current TransmittableThreadLocal in the parent class;}

two。 After assembling a WeakHashMap, it will eventually be included in our above constructor for the assignment of capturedRef.

Run@Overridepublic void run () {/ / 1. Gets the TtlRunnable object that was initialized when the capturedRef object was just constructed. Contains the data of the parent thread Object captured = capturedRef.get (); if (captured = = null | | releaseTtlValueReferenceAfterRun & &! capturedRef.compareAndSet (captured, null)) {throw new IllegalStateException ("TTL value reference is released after run!");} / / clears the key that is not in captured, and in this child thread, reset the value Object backup = replay (captured) for all ThreadLocal Try {/ / executes the actual threading method runnable.run ();} finally {/ / does the restore work according to backup restore (backup);}} private static WeakHashMap replayTtlValues (@ NonNull WeakHashMap captured) {WeakHashMap backup = new WeakHashMap (); for (final Iterator iterator = holder.get (). KeySet (). Iterator (); iterator.hasNext ();) {TransmittableThreadLocal threadLocal = iterator.next () / / complete the local backup backup.put (threadLocal, threadLocal.get ()) of the current thread; / / clear the data, which is not in the captured. If (! captured.containsKey (threadLocal)) {iterator.remove (); threadLocal.superRemove ();}} / / this is to set the value to the TransmittableThreadLocal of the current thread. SetTtlValuesTo (captured); / / A hook doExecuteCallback (true); return backup;} at this point, the study on "how to solve the value passing problem of pooled multiplex threads by TransmittableThreadLocal" is over, hoping to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report