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

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

时间: 2024-10-25 13:11:23

Java多线程10:ThreadLocal的作用及使用的相关文章

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

原创整理不易,转载请注明出处:java多线程模式ThreadLocal原理简述及其使用详解 代码下载地址:http://www.zuidaima.com/share/1781557457128448.htm ThreadLocal是为了使每个线程保存一份属于自己的数据. 先看一个使用ThreadLocal的实例. package com.zuidaima.aop.framework; import com.zuidaima.core.NamedThreadLocal; public abstra

java多线程--------深入分析 ThreadLocal 内存泄漏问题

前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能会导致内存泄漏.下面,我们将围绕三个方面来分析ThreadLocal 内存泄漏的问题 ThreadLocal 实现原理 ThreadLocal为什么会内存泄漏 ThreadLocal 最佳实践 ThreadLocal 实现原理 ThreadLocal的实现是这样的:每个Thread 维护一个 Thr

Java 多线程之--ThreadLocal 简介

<span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> 在多线程开发中,经常会遇见在run方法里面调用一个公共的属性的事情,由于每次start都会创建一个线程,因此</span> <span style="font-size: 18px; font-family: Arial,

java 多线程(threadlocal)

package com.example; import java.util.Random; public class App { public static class MyRunnable1 implements Runnable { //ThreadLocal是一个线程局部变量 private ThreadLocal<String> threadlocal = new ThreadLocal<String>(); @Override public void run() { //

java多线程学习-ThreadLocal

为了凑字,把oracle文档里介绍ThreadLocal抄过来 public class ThreadLocal<T> extends Object This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its ow

java 多线程 day06 threadLocal

import java.util.HashMap;import java.util.Map;import java.util.Random; /** * Created by chengtao on 17/12/3. * 继5 之后,ThreadLocal就是系统为我们提供的那个map */public class Thread0601_ThreadLocal { private static int data = 0; private static ThreadLocal<Integer>

java多线程10.构建同步工具

创建状态依赖类的最简单方法通常是在类库中现有状态依赖类的基础上进行构造.如果类库中没有提供你需要的功能,可以使用java语言和类库提供的底层机制来构造自己的同步机制,包括内置的条件队列.显示地Condition对象以及AbstractQueuedSynchronizer框架. 在单线程程序中调用方法时,如果基于某个状态的前提条件未得到满足,那么这个条件永远无法成真.而在并发程序中,基于状态的条件可能会由于其他线程的操作而改变.可阻塞的状态依赖操作 acquire lock on object s

java多线程关键字volatile的使用

java多线程关键字volatile的作用是表示多个线程对这个变量共享. 如果是只读的就可以直接用,写数据的时候要注意同步问题. 例子: package com.ming.thread.volatiletesttrhead1; /** * volatile 关键字的使用 * volatile 这个关键字的作用就是保持由此关键字修饰的变量在多个线程之间可以看得见 * @author mingge * */ public class volatiletesttrhead extends Thread

java多线程18: ThreadLocal的作用

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