从上一篇对于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给取出来了,是不是一个很好的解决方案呢?

在这里我原先也写了篇笔记 ,可以先看看java 中的 ThreadLocal

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设置值的话,是会返回null的



ThreadLocal.get 返回null解决




上面的对threadlocal 进行了初始化,从而没有进入 判断为null的if分支




InheritableThreadLocal的使用,值继承,继承父线程InheritableThreadLocal的值






从上面可以看得出来,使用InheritableThreadLocal子线程会自动继承父线程的InheritableThreadLocal值




InheritableThreadLocal值继承再修改




跟上面一样,继承childValue可以在子线程使用InheritableThreadLocal自动调用这个方法初始化子线程的值,记住只是初始化,也就是只执行一次,当父线程再次修改InheritableThreadLocal的值时,子线程取的就是父线程修改后的值了







java多线程18: ThreadLocal的作用的更多相关文章

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

    前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能 ...

  2. Java多线程之 ThreadLocal

    一.什么是ThreadLocal? 顾名思义它是local variable(线程局部变量).它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副 ...

  3. Java多线程基础-ThreadLocal

    感谢原文作者:Yuicon 原文链接:https://segmentfault.com/a/1190000016705955 序 在多线程环境下,访问非线程安全的变量时必须进行线程同步,例如使用 sy ...

  4. java 多线程(threadlocal)

    package com.example; import java.util.Random; public class App { public static class MyRunnable1 imp ...

  5. java多线程学习-ThreadLocal

    为了凑字,把oracle文档里介绍ThreadLocal抄过来 public class ThreadLocal<T> extends Object This class provides ...

  6. Java多线程:ThreadLocal

    一.ThreadLocal基础知识 ThreadLocal是线程的一个本地化对象,或者说是局部变量.当工作于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的 ...

  7. Java——多线程---18.11.22

    多线程代码:Runnable方法 package com.hebust.java.third; import java.util.Random; public class SaleTicket imp ...

  8. java 多线程 day06 threadLocal

    import java.util.HashMap;import java.util.Map;import java.util.Random; /** * Created by chengtao on ...

  9. java 多线程 :ThreadLocal 共享变量多线程不同值方案;InheritableThreadLocal变量子线程中自定义值,孙线程可继承

      ThreadLocal类的使用 变量值的共享可以使用public static变量的形式,所有的线程都是用同一个public static变量.如果想实现每一个线程都有自己的值.该变量可通过Thr ...

随机推荐

  1. 详解iOS多图下载的缓存机制

    1. 需求点是什么? 这里所说的多图下载,就是要在tableview的每一个cell里显示一张图片,而且这些图片都需要从网上下载. 2. 容易遇到的问题 如果不知道或不使用异步操作和缓存机制,那么写出 ...

  2. kafka负载均衡相关资料收集(三)

    apache kafka系列之Producer处理逻辑 下文是转载的,原文链接地址:点这儿 [转] Kafka ProducerKafka Producer处理逻辑kafka生产者处理逻辑apache ...

  3. Fusion-io ioDrive Duo Enterprise PCIe Review

    原文地址:http://www.storagereview.com/fusionio_iodrive_duo_enterprise_pcie_review As part of StorageRevi ...

  4. Ceph BlueFS

    一.概述 BlueFS是个小型文件系统,小体现在功能简单,没有实现Posix接口,不支持对文件的覆盖写操作只支持追加写,没有本地文件系统的树形层次结构,只有扁平的目录到文件的映射关系.和BlueSto ...

  5. iOS 限制输入字数完美解决方案

    关于限制输入字数以前也做过,网上也很多方法.但都不够完美,本方法可防止中文联想.粘贴等突破长途限制.可防止Emoji截为两半导致编码出问题.   - (void)textFieldDidChange: ...

  6. numpy 基于现有数据创建ndarray(from existing data)

    1 numpy.array array(object[, dtype=None, copy=True, order='K', subok=False, ndmin=0]) 2 numpy.asarra ...

  7. 关于ps cs5的一些问题

    一.photoshop cs5 默认在窗口中浮动方法 1.打开“编辑>首选项>界面”在“面板和文档”里把“以选项卡方式打开图像”的勾选去掉 2.点击菜单栏“窗口>排列>使所有内 ...

  8. linux的0号进程和1号进程

    linux的 0号进程 和 1 号进程 Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2) * idle进程由系统自动创 ...

  9. Hibernate 连接访问多个数据库(含访问不同数据库的相同表)(转)

    利用hibernate访问不同数据库中的不同表或不同数据库中的相同表. 本人在开发过程中的解决方案,希望大家交流.一般用myEclipse工具会自动生成Hibernate的相关文件,大致有下面几类: ...

  10. MySQL 示例数据库 employees 详解

    [引子] IT这一行在我看来是比较要求动手能力的,但是人非生而知之:人们身上的技能除了一些本能之外,大多都是通过学习而得到的. 前一段时间一直在整理素材,写一个关于explain 的系列文章:在一开始 ...