`
lwj0212
  • 浏览: 49630 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

线程级变量的理解和使用-ThreadLocal

阅读更多
1、概念 
早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。
 

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。

 

2、原理

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

代码清单1 SimpleThreadLocal,仅仅实现set,get方法做示例, 它和JDK所提供的ThreadLocal类在实现思路上是相近的

public class SimpleThreadLocal {
private Map valueMap = Collections.synchronizedMap(new HashMap());
public void set(Object newValue) {
    valueMap.put(Thread.currentThread(), newValue);①键为线程对象,值为本线程的变量副本
}
public Object get() {
Thread currentThread = Thread.currentThread();
Object o = valueMap.get(currentThread);②返回本线程对应的变量
if (o == null && !valueMap.containsKey(currentThread)) {③如果在Map中不存在,放到Map
中保存起来。
o = initialValue();
valueMap.put(currentThread, o);
}
    return o;
}
}

 

解释

 

总之,ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。归纳了两点:
1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。
 
简单来说,当你的一个线程需要经过很多个对象处理时,每个对象都需要使用到同一个变量,1个做法就是不停的传递该变量。另1做发就是使用ThreadLocal,把这个变量作为线程级的变量。
 
请看示例代码:
public class TestThreadLocal {
    static ThreadLocal tl1 = new ThreadLocal();
    class TLocal1 implements Runnable{
        void init() {
            tl1.set(new Object());
        }
        /* (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            init();
            try {
                Thread.sleep(1000);//暂停1秒,第2个线程应该也执行过init了吧
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " run:" + tl1.get());
            new TLocal2().print();
        }
    }
    
    class TLocal2 {
        public void print(){
            System.out.println(Thread.currentThread().getName() + " print:" + tl1.get());
        }
    }
    
    public static void main(String[] arg0) {
        TestThreadLocal test = new TestThreadLocal();
        Thread t1 = new Thread(test.new TLocal1(), "t1");
        Thread t2 = new Thread(test.new TLocal1(), "t2");
        t1.start();
        t2.start();
    }
}
 
运行结果:同一个线程里,得到的总司本线程里的对象
t1 run:java.lang.Object@10b30a7
t2 run:java.lang.Object@1b67f74
t1 print:java.lang.Object@10b30a7
t2 print:java.lang.Object@1b67f74

 

分享到:
评论

相关推荐

    java事务 - threadlocal

    Java事务和ThreadLocal是两种在Java编程中至关重要的概念,它们分别用于处理多线程环境下的数据一致性问题和提供线程局部变量。 首先,我们来深入理解Java事务。在数据库操作中,事务是一系列操作的集合,这些操作...

    Spring事务处理-ThreadLocal的使用

    本篇文章将聚焦于Spring事务处理中ThreadLocal的使用,以及如何通过源码理解和应用这个工具。 首先,了解Spring事务管理的基本概念。在多线程环境中,事务管理是至关重要的,它负责确保一组数据库操作要么全部成功...

    java多线程_java多线程下变量共享_

    Java多线程是Java编程中的重要概念,它允许...理解并掌握Java多线程下变量共享的原理和解决方案,有助于编写出高效、稳定的并发程序。在实际开发中,应结合具体业务场景选择合适的同步机制,以达到最佳性能和安全性。

    Synchronized与ThreadLocal

    **ThreadLocal** 提供了一种线程本地存储的解决方案,为每个线程创建独立的副本,避免了线程间的共享和争用问题。 - **作用原理:** - ThreadLocal 维护了一个 Map 结构,其中 Key 是 ThreadLocal 对象本身,Value...

    threadLocal

    ThreadLocal是Java编程语言中的一个线程局部变量类,它为每个线程提供了一个独立的变量副本,使得每个线程可以独立地改变...通过阅读和理解这些资料,开发者可以深化对ThreadLocal的理解,并将其有效地应用于项目中。

    C#多线程高级知识讲解

    5. **线程局部存储**:`ThreadLocal<T>`类允许创建每个线程都有独立副本的变量,这对于线程安全的缓存或线程特定的数据存储很有用。 6. **线程优先级**:虽然可以设置线程的优先级,但不推荐过度依赖,因为操作系统...

    线程并发时 本地变量和Lock锁的效率比较

    在Java中,可以使用`ThreadLocal`类来创建线程本地变量。使用本地变量可以简化代码,因为不需要进行同步操作,但需要注意的是,如果变量不再使用,记得及时清理,防止内存泄漏。 **Lock锁** Lock锁是一种显式同步...

    java线程 线程学习资料 java线程教程

    - **学习成果**: 学习者能够掌握编写简单的多线程程序的能力,并能够理解和分析使用线程的基本程序。 #### 二、线程基础知识 - **线程定义**: 在计算机科学中,线程是指程序执行流的一个单元,是操作系统调度的基本...

    Java多线程运算集合

    - Java提供了一种特殊类型的变量——`ThreadLocal` 变量,它可以为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变自己的副本,而不会影响其他线程。 #### 四、Java线程状态的转换 - **线程状态**...

    Java多线程-知识点梳理和总结-超详细-面试知识点.docx

    Thread安全可以通过使用线程同步机制、线程安全的数据结构和ThreadLocal变量等方式来实现。 CAS操作 CAS(Compare And Swap)是Java中的一种原子操作,用于解决多线程环境下的数据竞争问题。CAS操作可以将变量的...

    Java Threads英文第三版

    - 第七章专门讨论了线程和Swing UI框架的交互,包括Swing的线程限制、事件分派线程上的处理、invokeLater()和invokeAndWait()方法的使用,以及长时间运行的事件回调问题。 8. **线程和集合类** - 第八章讲述了...

    笔试面试题国内知名公司

    - 面试题可能涉及ArrayList、LinkedList、HashSet、HashMap等容器的使用和性能比较 - 泛型的理解和应用 - 接口和抽象类的区别 - 序列化 3. **Java面向对象编程** - 设计模式:单例、工厂、观察者、装饰器等 -...

    多线程基础部分.md,学习代码

    在IT行业中,多线程是实现高...总结来说,多线程基础部分的学习涵盖了线程创建、线程状态、线程同步、ThreadLocal的使用以及并发编程的高级概念。通过深入理解这些内容,开发者可以编写出更加高效、稳定的多线程程序。

    C#.NET多线程实例6个(包括多线程基本使用,多线程互斥等全部多线程使用实例)-f9.rar

    - **线程局部存储(ThreadLocal)**:每个线程拥有独立的变量副本,避免共享状态带来的问题。 7. **事件和委托**: - **事件**:用于线程间通信,一个线程触发事件,其他线程通过订阅事件进行响应。 - **委托**:...

    java线程例子大全

    Java线程是并发编程的核心部分,它允许程序同时执行多个任务,从而提高系统效率和响应速度。...以上知识点涵盖了Java线程的基本概念、操作和高级特性,通过这些例子,开发者可以深入理解并熟练运用Java的并发编程技术。

    Java多线程应用练习源代码及相关说明资料

    Java多线程是Java编程中的核心概念,尤其对于后端开发人员来说,理解和掌握多线程技术至关重要。这个压缩包包含的"Java多线程应用练习源代码及相关说明资料"是一份宝贵的资源,旨在帮助学习者深入理解并实践Java的...

    JavaEE DBUtil结合ThreadLocal的一个案例

    在JavaEE开发中,数据库操作是必不可少的一部分。DBUtil(Database Utility)通常是一个自定义的...它通过线程局部变量隔离了数据库连接,减少了资源争抢,同时简化了事务管理,是企业级Java应用开发中的常见实践。

    java thread的教程

    完成本教程后,读者应能够编写简单的多线程程序,并能理解和阅读使用线程的简单程序。 **作者简介:** Brian Goetz 是一位拥有超过15年专业软件开发经验的资深专栏作家,目前担任位于加利福尼亚州洛斯阿尔托斯的...

    c#线程参考手册

    - 使用ThreadLocal类可以在同一进程中为每个线程提供独立的变量副本。 - 这使得无需外部同步即可安全地使用局部存储变量。 9. 线程优先级和调度: - 线程优先级可以设置为从最高到最低的几个级别,线程调度器...

Global site tag (gtag.js) - Google Analytics