在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。

  当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

  从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。

  所以,在Java中编写线程局部变量的代码相对来说要笨拙一些,因此造成线程局部变量没有在Java开发者中得到很好的普及。

ThreadLocal的接口方法

ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

  • void set(Object value)设置当前线程的线程局部变量的值。
  • public Object get()该方法返回当前线程所对应的线程局部变量。
  • public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
  • protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

  值得一提的是,在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal<T>。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。

  ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。我们自己就可以提供一个简单的实现版本:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    package com.test; 
       
    public class TestNum { 
        // ①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 
        private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() { 
            public Integer initialValue() { 
                return 0
            
        }; 
       
        // ②获取下一个序列值 
        public int getNextNum() { 
            seqNum.set(seqNum.get() + 1); 
            return seqNum.get(); 
        
       
        public static void main(String[] args) { 
            TestNum sn = new TestNum(); 
            // ③ 3个线程共享sn,各自产生序列号 
            TestClient t1 = new TestClient(sn); 
            TestClient t2 = new TestClient(sn); 
            TestClient t3 = new TestClient(sn); 
            t1.start(); 
            t2.start(); 
            t3.start(); 
        
       
        private static class TestClient extends Thread { 
            private TestNum sn; 
       
            public TestClient(TestNum sn) { 
                this.sn = sn; 
            
       
            public void run() { 
                for (int i = 0; i < 3; i++) { 
                    // ④每个线程打出3个序列值 
                    System.out.println("thread[" + Thread.currentThread().getName() + "] --> sn[" 
                             + sn.getNextNum() + "]"); 
                
            
        
    }

ThreadLocal()理解的更多相关文章

  1. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

  2. 谈话Java在ThreadLocal理解类

    我们必须先了解:ThreadLocal不超过一个线程类,或者它应该被称为线程局部变量.这从ThreadLocal的JDK我们可以看到的定义 public class ThreadLocal<T& ...

  3. java ThreadLocal理解和使用

    一.ThreadLoal的理解 ThreadLoal 变量,它的基本原理是,同一个 ThreadLocal 所包含的对象(对ThreadLocal< String >而言即为 String ...

  4. Java ThreadLocal 理解

    ThreadLocal 概念: ThreadLocal不是用来解决对象共享访问的问题,而主要是提供了保存对象的方法和避免参数传递的方便的对象访问方式. ThreadLocal并不是一个Thread,而 ...

  5. ThreadLocal理解

    ThreadLocal 概述 ThreadLocal实例仅作为线程局部变量的==操作类==,以及==线程存储局部变量时的Key==.真正的线程局部变量是存储在各自线程的本地,通过Thread类中的Th ...

  6. ThreadLocal 理解

    主要方法 public void set(T value); public T get(); private T setInitialValue(); public void set(T value) ...

  7. 我是如何理解ThreadLocal

    ThreadLocal的概念 ThreadLocal从英文的角度看,可以看成thread和local的组合,就是线程本地的意思,我们都知道,看过jvm内存分配的人都知道在jvm虚拟机中对每一个线程都分 ...

  8. ThreadLocal的理解与应用场景分析

    对于Java ThreadLocal的理解与应用场景分析 一.对ThreadLocal理解 ThreadLocal提供一个方便的方式,可以根据不同的线程存放一些不同的特征属性,可以方便的在线程中进行存 ...

  9. 深入理解线程本地变量ThreadLocal

    ThreadLocal理解: 假设在多线程并发环境中.一个可变对象涉及到共享与竞争,那么该可变对象就一定会涉及到线程间同步操作,这是多线程并发问题. 否则该可变对象将作为线程私有对象,可通过Threa ...

  10. JavaSe:ThreadLocal

    JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...

随机推荐

  1. 微信JSApi支付~微信支付代理模式的实现(原创)

    返回目录 起因(大叔原创) 对于微信支付来说,你的发起者需要配置对应的域名来获取code(获取用户信息接口),而这意味着,你的多个项目(域名不同)不能同时使用一个公众号,这是一件很操蛋的事,对于我们开 ...

  2. 好股Android客户端开发

    按比例排列      TextView 文字对齐 webview和js之间的交互      在WebView中如何让JS与Java安全地相互调用 Android Http请求方法汇总          ...

  3. 关于Spring/Hibernate 3.x升级4.x的小问题

    情景:   之前版本 现在版本 JDK 1.7 1.8 Tomcat v7.0 v8.0 Spring 3.x 4.x Hibernate 3.x 4.x MySQL 忘了 5.1.53 分析: 如果 ...

  4. 游标的使用——mysql

    CREATE DEFINER=`root`@`%` PROCEDURE `split_category_all`()BEGIN declare categ varchar(10); ##套餐列 dec ...

  5. xml与datatable类型互换

    //已测 private DataTable ConvertXMLToDataSet(string xmlData) { StringReader stream = null; XmlTextRead ...

  6. js 理解new的运行机制

    先上段代码: function People(name) { this.name = name; } People.prototype.sayName = function () { console. ...

  7. (转)SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  8. Linux安全基础:awk命令的使用

    awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...

  9. 为阿里云站点部署免费 HTTPS

    本文记录了部署在阿里云的站点,在申请了免费的 SSL 证书后如何正确的部署到站点上,让站点支持 HTTPS 访问. 阿里云引入了沃通作为 CA 证书供应商,并开放了免费 SSL 申请的页面,之前一直想 ...

  10. MyEclipse 2016 CI 3发布

    JSjet 语法高亮 受够了Eclipse中的JavaScript编码体验?那就来试试MyEclipse 2016 CI 3.JSjet改进了JavaScript编码的语法高亮功能,大大提升了代码的可 ...