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 输出最终结果