关闭

Java多线程10:ThreadLocal的作用及使用

标签: java多线程线程线程安全
254人阅读 评论(0) 收藏 举报
分类:

ThreadLocal的作用

从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal.ThreadLocalMap里的是是线程自己要存储的对象,其他线程不需要去访问,也是访问不到的。各个线程中的ThreadLocal.ThreadLocalMap以及ThreadLocal.ThreadLocal中的值都是不同的对象。

至于为什么要使用ThreadLocal,不妨这么考虑这个问题。Java Web中,写一个Servlet:

复制代码
public class Servlet extends HttpServlet
{

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        this.doGet(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        
    }
}
复制代码

我在一个普通JavaBean内想拿到这个HttpServletRequest,但是无法通过参数传递的方式:

复制代码
public class OperateRequest
{
    public String operateRequest()
    {
        return null;
    }
}
复制代码

这时候怎么办?第一个解决方案,Servlet类中定义一个全局的HttpServletRequest,至于怎么定义就随便了,可以定义成静态的,也可以定义成非静态的但是对外提供setter/getter,然后operateRequest()方法每次都取这个全局的HttpServletRequest就可以了。

不否认,这是一种可行的解决方案,但是这种解决方案有一个很大的缺点:竞争。既然HttpServletRequest是全局的,那势必要引入同步机制来保证线程安全性,引入同步机制意味着牺牲响应给用户的时间----这在注重与用户之间响应的Java Web中是难以容忍的。

所以,我们引入ThreadLocal,既然ThreadLocal.ThreadLocalMap是线程独有的,别的线程访问不了也没必要访问,那我们通过ThreadLocal把HttpServletRequest设置到线程的ThreadLocal.ThreadLocalMap里面去不就好了?这样,在一次请求中哪里需要用到HttpServletRequest,就使用ThreadLocal的get()方法就把这个HttpServletRequest给取出来了,是不是一个很好的解决方案呢?

 

ThreadLocal使用

忘记上面那个复杂的问题,我们来看一下ThreadLocal的简单使用,首先ThreadLocal肯定是全局共享的:

public class Tools
{
    public static ThreadLocal<String> t1 = new ThreadLocal<String>();
}

写一个线程往ThreadLocal里面塞值:

复制代码
public class ThreadLocalThread extends Thread
{
    private static AtomicInteger ai = new AtomicInteger();
    
    public ThreadLocalThread(String name)
    {
        super(name);
    }
    
    public void run()
    {
        try
        {
            for (int i = 0; i < 3; i++)
            {
                Tools.t1.set(ai.addAndGet(1) + "");
                System.out.println(this.getName() + " get value--->" + Tools.t1.get());
                Thread.sleep(200);
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
复制代码

写个main函数,启动三个ThreadLocalThread:

复制代码
public static void main(String[] args) throws Exception
    {
        ThreadLocalThread a = new ThreadLocalThread("ThreadA");
        ThreadLocalThread b = new ThreadLocalThread("ThreadB");
        ThreadLocalThread c = new ThreadLocalThread("ThreadC");
        a.start();
        b.start();
        c.start();
    }
复制代码

看一下运行结果:

复制代码
ThreadA get value--->1
ThreadC get value--->2
ThreadB get value--->3
ThreadB get value--->4
ThreadC get value--->6
ThreadA get value--->5
ThreadC get value--->8
ThreadA get value--->7
ThreadB get value--->9
复制代码

看到每个线程的里都有自己的String,并且互不影响----因为绝对不可能出现数字重复的情况。用一个ThreadLocal也可以多次set一个数据,set仅仅表示的是线程的ThreadLocal.ThreadLocalMap中table的某一位置的value被覆盖成你最新设置的那个数据而已,对于同一个ThreadLocal对象而言,set后,table中绝不会多出一个数据

 

ThreadLocal再总结

上一篇文章的最后有对ThreadLocal的工作原理进行总结,这里对ThreadLocal再次进行一个总结:

1、ThreadLocal不是集合,它不存储任何内容,真正存储数据的集合在Thread中。ThreadLocal只是一个工具,一个往各个线程的ThreadLocal.ThreadLocalMap中table的某一位置set一个值的工具而已

2、同步与ThreadLocal是解决多线程中数据访问问题的两种思路,前者是数据共享的思路后者是数据隔离的思路

3、同步是一种以时间换空间的思想,ThreadLocal是一种空间换时间的思想

4、ThreadLocal既然是与线程相关的,那么对于Java Web来讲,ThreadLocal设置的值只在一次请求中有效,是不是和request很像?因为request里面的内容也只在一次请求有效,对比一下二者的区别:

(1)ThreadLocal只能存一个值,一个Request由于是Map形式的,可以用key-value形式存多个值

(2)ThreadLocal一般用在框架,Request一般用在表示层、Action、Servlet

0
0
查看评论

java多线程模式ThreadLocal原理简述及其使用详解

java多线程模式ThreadLocal原理简述及其使用详解,代码下载地址:http://www.zuidaima.com/share/1781557457128448.htm
  • yaerfeng
  • yaerfeng
  • 2014-05-18 11:51
  • 5514

java ThreadLocal(应用场景及使用方式及原理)

Thread.java源码中: ThreadLocal.ThreadLocalMap threadLocals = null;即:每个Thread对象都有一个ThreadLocal.ThreadLocalMap成员变量,ThreadLocal.ThreadLocalMap是一个ThreadLocal...
  • qilixiang012
  • qilixiang012
  • 2014-07-30 10:15
  • 6191

Java--servlet + ThreadLocal解决多线程并发问题及实例

思维导图 – Servlet+ThreadLocal分包管理实例一:本文思维导图 二:ThreadLocal原理图 三:代码:实体层entity Book.javapackage entity;public class Book { /*私有属性*/ private int i...
  • u014421677
  • u014421677
  • 2016-06-25 11:15
  • 454

java多线程--深入理解threadlocal以及适用场景

如何使用:       简介: JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个Thr...
  • sean417
  • sean417
  • 2017-04-10 15:51
  • 771

Java中ThreadLocal类的作用以及实现原理-----hibernate的连接池就是用ThreadLocal实现的

Why ThreadLocal? 无论如何,要编写一个多线程安全(Thread-safe)的程序是困难的,为了让线程共享资源,必须小心地对共享资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同步的时候,又要注意对象的锁定与释放,避免产生死结,种种因素都使得编写多线程程序变得困难。 尝试从另一...
  • wenzhihui_2010
  • wenzhihui_2010
  • 2013-05-28 16:50
  • 1231

java多线程并发控制之ThreadLocal

下面是ThreadLocal的测试代码,更多信息请参考注释 package com.jadyer.thread.local;      import java.util.Random;   ...
  • maguanghui_2012
  • maguanghui_2012
  • 2017-02-11 11:41
  • 732

Java ThreadLocal解决线程安全问题

TLS:Thread Local Storage   转载自http://blog.csdn.net/jiht594/article/details/6606326  TLS全称为Thread Local Storage,是Windows为解决一个进程中多个线程同时访问全局变量而提供的机制。TL...
  • bestcxx
  • bestcxx
  • 2017-02-10 23:11
  • 592

ThreadLocal的设计理念与作用

Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量。 如何创建ThreadLocal变量 以下代码展示了如何创建一个Thre...
  • u011860731
  • u011860731
  • 2015-09-25 14:37
  • 5655

【java项目实战】ThreadLocal封装Connection,实现同一线程共享资源

线程安全一直是程序猿们关注的焦点,多线程也一直是比较让人头疼的话题,想必大家曾经也遇到过各种各种的问题,我就不再累述了。当然,解决方式也有很多,这篇博文给大家提供一种很好的解决线程安全问题的思路。 。。。。。。   ThreadLocal是解决线程安全问题一个很好的思路,在很多情况下...
  • jiuqiyuliang
  • jiuqiyuliang
  • 2014-08-08 08:02
  • 9161

从头认识多线程-4.3 ThreadLocal使用时需要注意的地方

4.3 这一章节我们来讨论一下关于ThreadLocal的使用的时候需要注意的地方ThreadLocal主要的使用是get、set、initialValue这几个方法,具体的使用我们这里不做介绍,下面只是举一些它使用的时候需要注意的地方。1.在get方法的时候出现nullpackage com.ra...
  • raylee2007
  • raylee2007
  • 2016-06-17 15:47
  • 3875
    个人资料
    • 访问:46303次
    • 积分:833
    • 等级:
    • 排名:千里之外
    • 原创:19篇
    • 转载:112篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论