threadlocal应用场景使用方式介绍java

KLQ 2020-06-02 15:38:51 java常见问答 6127

你知道threadlocal的应用场景是怎样的吗?你知道threadlocal使用方式吗?下面的文章就是要给大家介绍这两个方面的内容,一起来了解一下吧。

首先我们来讲一下threadlocal应用场景,为了可以将threadlocal应用场景讲清楚,下面就以一个框架作为示例。

Spring的事务管理器通过AOP切入业务代码,在进入业务代码之前,会根据相应的事务管理器提取出相应的事务对象。

假如说,事务管理器是DataSourceTransactionManager,那么就会从DataSource当中获得一个连接对象,经过一定的包装过后,将它保存在ThreadLocal当中。

除此之外,Spring也对DataSource进行了包装,重写了其中的getConnection()方法,又或者是说,这个方法的返回将会由Spring来控制。

这样的话,Spring就可以使得线程内多次获取到的Connection对象是同一个。

那么,这里有一个问题了,放在threadlocal里面这是为什么呢?

这主要是因为Spring在AOP后并不可以向应用程序传递參数。

应用程序的每一个业务代码都是事先定义好的,Spring并不会要求在业务代码的入口參数中必须编写Connection的入口參数。

这个时候,Spring选择了threadlocal。

通过threadlocal保证连接对象始终在线程内部,也就是不管在什么时候都可以拿到。

那么这样的话,Spring就会非常的清楚在什么时候回收这个连接,也就是很明白,什么时候从threadlocal当中删除这个元素。

那么,从Spring事务管理器的设计上面可以看出,Spring利用threadlocal得到了一个非常好的设计思路。

与此同时它在设计的时候,也十分的清楚threadlocal中元素应该在什么时候删除。

所以,简单地觉得ThreadLocal尽量使用在一个全局的设计上,而不是说,一种打补丁的间接方法。

对于这些基本应用场景你都了解了吗?

那么下面,就一起来看一下具体的示例吧。

定义一个类用于存放静态的ThreadLocal对象,通过多个线程并行地对ThreadLocal对象进行set、get操作,并将值进行打印。

代码:

public class ThreadLocalTest
{
    static class ResourceClass
    {
        public final static ThreadLocal < String > RESOURCE_1 =
            new ThreadLocal < String > ();
        public final static ThreadLocal < String > RESOURCE_2 =
            new ThreadLocal < String > ();
    }
    static class A
    {
        public void setOne(String value)
        {
            ResourceClass.RESOURCE_1.set(value);
        }
        public void setTwo(String value)
        {
            ResourceClass.RESOURCE_2.set(value);
        }
    }
    static class B
    {
        public void display()
        {
            System.out.println(ResourceClass.RESOURCE_1.get() +
                ":" + ResourceClass.RESOURCE_2.get());
        }
    }
    public static void main(String[] args)
    {
        final A a = new A();
        final B b = new B();
        for (int i = 0; i < 15; i++)
        {
            final String resouce1 = "线程-" + I;
            final String resouce2 = " value = (" + i + ")";
            new Thread()
            {
                public void run()
                {
                    try
                    {
                        a.setOne(resouce1);
                        a.setTwo(resouce2);
                        b.display();
                    }
                    finally
                    {
                        ResourceClass.RESOURCE_1.remove();
                        ResourceClass.RESOURCE_2.remove();
                    }
                }
            }.start();
        }
    }
}

测试结果

线程-6: value = (6)

线程-9: value = (9)

线程-0: value = (0)

线程-10: value = (10)

线程-12: value = (12)

线程-14: value = (14)

线程-11: value = (11)

线程-3: value = (3)

线程-5: value = (5)

线程-13: value = (13)

线程-2: value = (2)

线程-4: value = (4)

线程-8: value = (8)

线程-7: value = (7)

线程-1: value = (1)

可以很明显的看得出来,输出的线程顺序并不是最初定义线程的顺序。

理论上可以表示,多线程应当是并发运行的。

但是,依旧能够保持每一个线程里面的值是相应的,也就表示,这些值已经达到了线程私有的目的。

好了对于threadlocal应用场景及使用方式就给大家介绍到这里了,更多threadlocal常见问题,欢迎继续关注奇Q工具网来进行了解哦。

推荐阅读:

threadlocal原理是什么,原理详解