`
阅读更多

ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。

在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序缜密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
概述:
而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal为每一个线程提供一个独立的变量副本,从而隔离了多个线 程对访问数据的冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的对象封装,在编 写多线程代码时,可以把不安全的变量封装进ThreadLocal。

由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度上简化ThreadLocal的使用,代码清单9-2就使用了JDK 5.0新的ThreadLocal<T>版本。

概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式:访问串行化,对象共享化。而ThreadLocal采用了“以空 间换时间”的方式:访问并行化,对象独享化。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影 响。

 

一:先说下ThreadLocal的作用总结吧:

        当线程并发时,使用ThreadLocal在保证每个线程拥有自己的独立对象,线程间互不影响。

 

二:在说下ThreadLocal和Synchronized关键字对线程并发时锁定同意操作对象的区别

        前者线程并发拥有自己独立对象,做到操作对象的安全,但是它每个线程都会new一个操作对象的实例,这样一来,就损失了系统耗费内存的问题,但是性能有所提升!(以空间换时间)

        后者线程并发时可以用Synchronized关键字来对线程来同步执行,但是它只能单个线程执行,阻塞其他线程,这样一来,就损失了系统的性能,但是系统内存占用问题有所提高!(以时间换空间)

 

三:我们来看下ThreadLocal应用的demo

public class Student {

    private int age = 0; // 年龄

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

public class ThreadLocalDemo implements Runnable {

    // 创建线程局部变量studentLocal,在后面你会发现用来保存Student对象
    private final static ThreadLocal studentLocal = new ThreadLocal();

    public static void main(String[] agrs) {
        ThreadLocalDemo td = new ThreadLocalDemo();
        Thread t1 = new Thread(td, "a");
        Thread t2 = new Thread(td, "b");
        t1.start();
        t2.start();
    }

    public void run() {
        // TODO Auto-generated method stub
        accessStudent();
    }

    public void accessStudent() {
        // 获取当前线程的名字
        String currentThreadName = Thread.currentThread().getName();
        System.out.println(currentThreadName + " is running!");
        // 产生一个随机数并打印
        Random random = new Random();
        int age = random.nextInt(100);
        System.out.println("thread " + currentThreadName + " set age to:" + age);
        // 获取一个Student对象,并将随机数年龄插入到对象属性中
        Student student = getStudent();
        student.setAge(age);
        System.out.println("thread " + currentThreadName + " first read age is:" + student.getAge());
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        System.out.println("thread " + currentThreadName + " second read age is:" + student.getAge());
    }

    protected Student getStudent() {
        // 获取本地线程变量并强制转换为Student类型
        Student student = (Student) studentLocal.get();
        // 线程首次执行此方法的时候,studentLocal.get()肯定为null
        if (student == null) {
            // 创建一个Student对象,并保存到本地线程变量studentLocal中
            student = new Student();
            studentLocal.set(student);
        }
        return student;
    }

}

a is running!
b is running!
thread b set age to:15
thread a set age to:22
thread b first read age is:15
thread a first read age is:22
thread b second read age is:15
thread a second read age is:2
// 从得到的结果可以看出,线程之间的Student对象在每个线程中都拥有一个,做到互不干扰!

 为加强对ThreadLocal的认识,下面来看一个hibernate中典型的ThreadLocal的应用:

    private static final ThreadLocal threadSession = new ThreadLocal();  
      
    public static Session getSession() throws InfrastructureException {  
        Session s = (Session) threadSession.get();  
        try {  
            if (s == null) {  
                s = getSessionFactory().openSession();  
                threadSession.set(s);  
            }  
        } catch (HibernateException ex) {  
            throw new InfrastructureException(ex);  
        }  
        return s;  
    }  

 我们通过以上例子,不难看出ThreadLocal的应用场合,最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。

                                          

最后补充下,ThreadLocal常用的方法

T get()
          返回此线程局部变量的当前线程副本中的值。
protected  T initialValue()
          返回此线程局部变量的当前线程的初始值。
void remove()
          移除此线程局部变量的值。
void set(T value)
          将此线程局部变量的当前线程副本中的值设置为指定值。

1
3
分享到:
评论
4 楼 zhangliguoaccp 2015-10-14  
我说的是ThreadLocal是消耗内存在控制多线程并发,对象共享问题,这才是他的精髓!
而你说的是回收的问题,但应用它也是要考虑回收问题的
3 楼 cywhoyi 2015-10-14  
zhangliguoaccp 写道
不是吧兄弟,ThreadLocal是消耗内存在控制多线程并发,对象共享问题,这才是他的精髓吧

stackoverflow exception,如果使用不当TL会经常抛出,一般用完要remove,或者像Tomcat那样通过配合线程池进行反复使用
2 楼 zhangliguoaccp 2015-10-13  
不是吧兄弟,ThreadLocal是消耗内存在控制多线程并发,对象共享问题,这才是他的精髓吧
1 楼 cywhoyi 2015-10-12  
ThreadLocal属于线程副本的变量,更多使用场景是内存消耗可控制,要不然TL的回收是大问题

相关推荐

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

    "Java多线程-知识点梳理和总结-超详细-面试知识点" Java多线程是Java编程语言中最基本也是最重要的概念之一。多线程编程可以提高程序的执行效率、改善用户体验和提高系统的可扩展性。但是,多线程编程也存在一些...

    Java多线程 - (一) 最简单的线程安全问题

    在Java编程中,多线程是并发处理任务的关键技术,特别是在服务器端开发和高并发场景下。本篇文章将深入探讨“最简单的线程安全问题”,并结合相关源码和工具来帮助理解。线程安全问题通常涉及到多个线程对共享资源的...

    java ThreadLocal多线程专属的变量源码

    java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多...

    Java多线程 之 临界区、ThreadLocal.docx

    Java多线程编程中,临界区和ThreadLocal是两种重要的并发控制机制,它们用于解决多线程环境下的数据安全问题。 1. **临界区(Critical Section)** 临界区是指一段代码,它在同一时刻只允许一个线程进行访问。在...

    Java多线程-线程安全问题练习题

    在Java多线程编程中,线程安全问题是非常关键的概念,它涉及到多个线程访问共享资源时可能出现的数据不一致或异常情况。本题主要通过两个练习题来加深对线程安全的理解。 ### 练习题1:新年倒计时 #### 题目描述 ...

    Java多线程编程总结

    ### Java多线程编程总结 #### 一、Java线程:概念与原理 1. **操作系统中线程和进程的概念** - 当前的操作系统通常为多任务操作系统,多线程是实现多任务的一种手段。 - **进程**:指内存中运行的应用程序,每个...

    java多线程的讲解和实战

    Java多线程是Java编程中的重要概念,尤其在如今的多核处理器环境下,理解并熟练掌握多线程技术对于提高程序性能和响应速度至关重要。本资料详细讲解了Java多线程的原理,并提供了丰富的实战代码,非常适合Java初学者...

    java事务 - threadlocal

    总结一下,Java事务和ThreadLocal都是Java多线程编程中不可或缺的工具。事务用于保证数据库操作的原子性和一致性,ThreadLocal则为每个线程提供了独立的数据空间,避免了线程间的数据冲突。理解并熟练运用这两个概念...

    多线程-day02.docx

    在“多线程-day02”的学习资源中,我们深入探讨了Java内存模型以及多线程的特性与控制机制。 **Java内存模型** Java内存模型,也称为JVM内存模型,是Java程序员理解和掌握的基础知识,特别是在进行并发编程时。它...

    Java多线程的总结

    Java多线程是Java编程中的一个核心概念,它在现代软件开发中扮演着至关重要的角色。多线程允许程序同时执行多个任务,提高了系统资源的利用率,提升了应用程序的响应速度和并发性能。对于大型分布式系统、Web应用...

    java 多线程编程实战指南(核心 + 设计模式 完整版)

    《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...

    JAVA并发-自问自答学ThreadLocal.pdf

    总结起来,ThreadLocal是Java中实现线程局部变量的一种机制,它使得线程间的数据独立,避免了并发编程中的数据共享问题,简化了多线程环境下的状态管理。然而,使用ThreadLocal时必须注意内存管理和对象的生命周期,...

    java多线程编程总结

    ### Java多线程编程总结 #### 一、Java线程:概念与原理 - **操作系统中线程和进程的概念** 当前的操作系统通常都是多任务操作系统,多线程是一种实现多任务的方式之一。在操作系统层面,进程指的是内存中运行的...

    基于Java的源码-超简单Java多线程填表源码.zip

    这个"基于Java的源码-超简单Java多线程填表源码.zip"文件很可能包含一个简单的示例,演示如何在Java中使用多线程来填充表格数据。下面我们将深入探讨Java多线程的基础知识及其在实际应用中的使用。 1. **线程基础**...

    java多线程

    由于提供的文件内容大部分与Java多线程编程核心技术并无直接关联,而是关于电子书资源的联系方式和说明,因此不能直接从这部分内容中生成关于Java多线程的知识点。但考虑到描述中提到了电子书的标题以及它涉及的主题...

    java多线程设计

    总结,Java多线程设计是构建高性能、高并发应用的基础。通过理解并合理使用不可变对象,我们可以有效预防多线程环境中的非安全问题,确保程序的稳定性和正确性。在实际开发中,结合各种线程同步机制和并发工具,可以...

    我总结的Java多线程程序设计

    Java多线程程序设计是Java开发中的重要组成部分,它允许程序在同一时间执行多个任务,从而提高了系统的效率和响应性。本文将深入探讨Java多线程的相关概念和实现方式。 一、理解多线程 1. **线程定义**:线程是一...

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

    Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,从而提升系统效率。在多线程环境中,变量共享是一个常见的需求,但也是引发问题的关键点。本篇文章将深入探讨Java多线程下变量共享的问题以及解决...

    WHUT-java多线程实验-第二周-异常处理.zip

    Java多线程是Java编程中的核心概念,尤其在并发编程领域中扮演着至关重要的角色。在实际开发中,多线程能充分利用系统资源,提高程序的执行效率。本实验主要关注的是Java多线程中的异常处理,这在保证程序稳定性和...

    简单分析Java线程编程中ThreadLocal类的使用共

    Java线程编程中的ThreadLocal类是一个非常重要的工具,它在多线程环境下提供了一种线程局部变量的机制。ThreadLocal并非是简单的变量,而是一种能够确保每个线程都拥有独立副本的变量容器。理解ThreadLocal的工作...

Global site tag (gtag.js) - Google Analytics