阿里TTL异步执行上下文对象传递

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


验证对象异步传递示例:

package com.alibaba.ttl.threadpool.agent.demo;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import com.alibaba.ttl.TransmittableThreadLocal;

public final class AgentDemo {

    static TransmittableThreadLocal<String> stringTransmittableThreadLocal = new TransmittableThreadLocal<String>();

    static TransmittableThreadLocal<Person> personReferenceTransmittableThreadLocal = new TransmittableThreadLocal<Person>() {
        @Override
        protected Person initialValue() {
            return new Person("unnamed", -1);
        }
    };

    static TransmittableThreadLocal<Person> personCopyTransmittableThreadLocal = new TransmittableThreadLocal<Person>() {
        @Override
        protected Person copy(Person parentValue) {
            // copy value to child thread
            return new Person(parentValue.getName(), parentValue.getAge());
        }

        @Override
        protected Person initialValue() {
            return new Person("unnamed", -1);
        }
    };
    
    private AgentDemo() {
    	throw new InstantiationError( "Must not instantiate this class" );
    }

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        expandThreadPool(executorService);

        stringTransmittableThreadLocal.set("foo - main");
        personReferenceTransmittableThreadLocal.set(new Person("jerry - reference", 1));
        personCopyTransmittableThreadLocal.set(new Person("Tom - value", 2));

        printTtlInstancesInfo("Main - Before execution of thread pool");

        Future<?> submit = executorService.submit(new Runnable() {
            @Override
            public void run() {
                printTtlInstancesInfo("Thread Pool - enter");
                stringTransmittableThreadLocal.set("foo - modified in thread pool");
                personReferenceTransmittableThreadLocal.get().setName("jerry - reference - modified in thread pool");
                personCopyTransmittableThreadLocal.get().setName("Tom - value - modified in thread pool");
                printTtlInstancesInfo("Thread Pool - leave");
            }
        });
        submit.get();

        printTtlInstancesInfo("Main - After execution of thread pool");

        executorService.shutdown();
        if (!executorService.awaitTermination(3, TimeUnit.SECONDS)) {
            System.exit(1);
        }
    }

    public static void expandThreadPool(ExecutorService executor) throws Exception {
        List<Future<?>> ret = new ArrayList<Future<?>>();
        for (int i = 0; i < 3; ++i) {
            Future<?> submit = executor.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            ret.add(submit);
        }
        for (Future<?> future : ret) {
            future.get();
        }
    }

    static void printTtlInstancesInfo(String msg) {
        System.out.println("====================================================");
        System.out.println(msg);
        System.out.println("====================================================");
        System.out.println("stringTransmittableThreadLocal: " + stringTransmittableThreadLocal.get());
        System.out.println("personReferenceTransmittableThreadLocal: " + personReferenceTransmittableThreadLocal.get());
        System.out.println("personCopyTransmittableThreadLocal: " + personCopyTransmittableThreadLocal.get());
    }

    public static class Person {
        String name;
        int age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}

测试结果:

====================================================
Main - Before execution of thread pool
====================================================
stringTransmittableThreadLocal: foo - main
personReferenceTransmittableThreadLocal: Person{name='jerry - reference', age=1}
personCopyTransmittableThreadLocal: Person{name='Tom - value', age=2}
====================================================
Thread Pool - enter
====================================================
stringTransmittableThreadLocal: null
personReferenceTransmittableThreadLocal: Person{name='unnamed', age=-1}
personCopyTransmittableThreadLocal: Person{name='unnamed', age=-1}
====================================================
Thread Pool - leave
====================================================
stringTransmittableThreadLocal: foo - modified in thread pool
personReferenceTransmittableThreadLocal: Person{name='jerry - reference - modified in thread pool', age=-1}
personCopyTransmittableThreadLocal: Person{name='Tom - value - modified in thread pool', age=-1}
====================================================
Main - After execution of thread pool
====================================================
stringTransmittableThreadLocal: foo - main
personReferenceTransmittableThreadLocal: Person{name='jerry - reference', age=1}
personCopyTransmittableThreadLocal: Person{name='Tom - value', age=2}

分析:

-Before 初始化线程输出

-enter  线程重新设置传递对象的值,但并未提交,所以对象是一个默认的实例输出

-leave submit提交对象修改,对象值被修改传递赋值

-after 输出最终结果


Java 中,线程之间的变量传递是一件比较复杂的事情,因为线程之间是相互独立的,每个线程都有自己的栈空间和变量存储空间。在多线程编程中,我们经常需要在线程之间传递某些变量或者数据,这就需要使用一些特殊的技术来实现。 其中一种技术就是使用 TransmittableThreadLocal(TTL)类,它可以让我们在多个线程之间传递变量,而且还可以保证变量的值在每个线程中都是唯一的。 TTL 是一个线程局部变量的扩展,它可以让我们在一个线程中创建一个变量,并且在任何一个子线程中都能够访问到这个变量的值。而且,当子线程结束时,TTL 会自动回收这个变量。 下面是一个使用 TTL 的示例代码: ``` import com.alibaba.ttl.TransmittableThreadLocal; public class Demo { private static TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>(); public static void main(String[] args) { // 在主线程中设置值 threadLocal.set("value set in main thread"); // 创建子线程并启动 Thread thread = new Thread(() -> { // 在子线程中获取值 String value = threadLocal.get(); System.out.println("value in sub thread: " + value); }); thread.start(); } } ``` 在这个示例代码中,我们首先创建了一个 TTL 对象 threadLocal,然后在主线程中设置了一个值,接着创建了一个子线程,并在子线程中获取了这个值。当子线程结束时,TTL 会自动回收这个变量。 TTL 的原理比较简单,它使用了 Java 中的 InheritableThreadLocal 类来实现。当我们在主线程中创建了一个 TTL 变量时,它会将这个变量存储到 InheritableThreadLocal 中。当我们创建子线程时,子线程会继承主线程的 InheritableThreadLocal 对象,并且会在自己的线程空间中创建一个新的 TTL 变量,这个变量的值会从主线程中的变量中拷贝过来。当子线程结束时,TTL 会自动回收这个变量。 总的来说,TTL 是一个非常方便的工具,它可以让我们在多个线程之间传递变量,而且还能够保证变量的值在每个线程中都是唯一的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值