`

线程之ThreadLocal

阅读更多
1. 先看一个非ThreadLocal的例子
package thread;

/**
 */
public class ThreadLocalDemo {
	
    public ThreadLocalDemo() {};
    
    // 通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
    private static int seqNum = 0;
    
    // 获取下一个序列值
    public int getNextNum() {
    	
        return ++seqNum;
    }
    
    public static void main(String[] args) {
        
    	ThreadLocalDemo test = new ThreadLocalDemo();
        
        // 3个线程共享sn,各自产生序列号
    	TestClientDemo client1 = new TestClientDemo(test);
    	TestClientDemo client2 = new TestClientDemo(test);
    	TestClientDemo client3 = new TestClientDemo(test);
        
        client1.start();
        client2.start();
        client3.start();
    }
}
class TestClientDemo extends Thread {
    
    private ThreadLocalDemo test;
    
    /**
     * 构造函数.
     */
    public TestClientDemo() {};
    
    /**
     * 构造函数.
     */
    public TestClientDemo(ThreadLocalDemo test) {
        
        this.test = test;
    };
    
    @Override
    public void run() {
        
        //{④每个线程打出3个序列值
        for(int i=0 ; i<=3 ; i++) {
            
            System.err.println(Thread.currentThread().getName() + "===NextNum is:==" +test.getNextNum());
        }
    }
}

这是5个线程访问静态变量threadName的例子,看看输出。
Thread-0===NextNum is:==1
Thread-0===NextNum is:==2
Thread-0===NextNum is:==3
Thread-0===NextNum is:==4
Thread-1===NextNum is:==5
Thread-1===NextNum is:==6
Thread-1===NextNum is:==7
Thread-1===NextNum is:==8
Thread-2===NextNum is:==9
Thread-2===NextNum is:==10
Thread-2===NextNum is:==11
Thread-2===NextNum is:==12
可以看出3个线程共享了一个seqNum。

2. 再看一个ThreadLocal的例子
package thread;

/**
 */
public class ThreadLocalCamp {
	
    public ThreadLocalCamp() {};
    
    // 通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
    private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {     
        protected Integer initialValue() {
            return 0;
        }
    };
    
    // 获取下一个序列值
    public int getNextNum() {
        
        seqNum.set(seqNum.get()+1);
        return seqNum.get();
    }
    
    public static void main(String[] args) {
        
    	ThreadLocalCamp test = new ThreadLocalCamp();
        
        // 3个线程共享sn,各自产生序列号
        TestClient client1 = new TestClient(test);
        TestClient client2 = new TestClient(test);
        TestClient client3 = new TestClient(test);
        
        client1.start();
        client2.start();
        client3.start();
    }
}
class TestClient extends Thread {
    
    private ThreadLocalCamp test;
    
    /**
     * 构造函数.
     */
    public TestClient() {};
    
    /**
     * 构造函数.
     */
    public TestClient(ThreadLocalCamp test) {
        
        this.test = test;
    };
    
    @Override
    public void run() {
        
        //{④每个线程打出3个序列值
        for(int i=0 ; i<=3 ; i++) {
            
            System.err.println(Thread.currentThread().getName() + "===NextNum is:==" +test.getNextNum());
        }
    }
}

这两个类的区别就是第二个类的seqNum用了ThreadLocal:
private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {     
        protected Integer initialValue() {
            return 0;
        }
    };

看看第二个类的输出:
Thread-0===NextNum is:==1
Thread-2===NextNum is:==1
Thread-1===NextNum is:==1
Thread-2===NextNum is:==2
Thread-0===NextNum is:==2
Thread-2===NextNum is:==3
Thread-1===NextNum is:==2
Thread-2===NextNum is:==4
Thread-0===NextNum is:==3
Thread-0===NextNum is:==4
Thread-1===NextNum is:==3
Thread-1===NextNum is:==4
可以看出3个线程各自有一个seqNum。

3. 总结
该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。

API表达了下面几种观点:

1、ThreadLocal不是线程,是线程的一个变量,你可以先简单理解为线程类的属性变量。

2、ThreadLocal 在类中通常定义为静态类变量。

3、每个线程有自己的一个ThreadLocal,它是变量的一个‘拷贝’,修改它不影响其他线程。

既然定义为类变量,为何为每个线程维护一个副本(姑且成为‘拷贝’容易理解),让每个线程独立访问?多线程编程的经验告诉我们,对于线程共享资源(你可以理解为属性),资源是否被所有线程共享,也就是说这个资源被一个线程修改是否影响另一个线程的运行,如果影响我们需要使用synchronized同步,让线程顺序访问。

ThreadLocal适用于资源共享但不需要维护状态的情况,也就是一个线程对资源的修改,不影响另一个线程的运行;这种设计是‘空间换时间’,synchronized顺序执行是‘时间换取空间’。
分享到:
评论
1 楼 yuanq_20 2011-12-30  
可以学习一下jdk5线程池!

相关推荐

    ThreadLocal详解及说明

    关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. 关于线程变量ThreadLocal的介绍以及说明. ...

    线程ThreadLocal机制实现例子

    本例以序列号生成的程序为例,展示ThreadLocal的使用

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

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

    Java多线程编程之ThreadLocal线程范围内的共享变量

    主要介绍了Java多线程编程之ThreadLocal线程范围内的共享变量,本文讲解了ThreadLocal的作用和目的、ThreadLocal的应用场景、ThreadLocal的使用实例等,需要的朋友可以参考下

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

    简单分析Java线程编程中ThreadLocal类的使用共4页.pdf.zip

    ThreadLocal

    ThreadLocal入门教程。 讲解了线程安全和ThreadLocal的使用的基本知识。

    线程锁+ThreadLocal.docx

    多线程可以同时运行多个任务但是当多个线程同时访问共享数据时,可能导致数据不同步,甚至错误!线程锁主要用来给方法、代码块加锁

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

    synchronized关键字不属于方法特征签名的一部分,所以可以在覆盖方法的时候加上去。也就是说,在父类的方法声明上可以没有synchronized关键字,而在子类覆盖该方法时加上synchronized关键字。 注意:使用...

    详解Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失

    主要介绍了详解Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Java多线程编程中ThreadLocal类的用法及深入

    ThreadLocal,直译为“线程本地”或“本地线程”,如果你真的这么认为,那就错了!其实,它就是一个容器,用于存放线程的局部变量,我认为应该叫做 ThreadLocalVariable(线程局部变量)才对,真不理解为什么当初 ...

    ThreadLocal详解

    java 多线程 ThreadLocal

    TestNG多线程安全吗?ThreadLocal:有我还能不安全?

    目录一、背景介绍二、TestNG多线程详解2.1 TestNG多线程实现2.2 TestNG多线程效果演示三、ThreadLocal3.1 ThreadLocal概念3.2 具体实现 一、背景介绍  在使用Selenium+TestNG做WebUI自动化过程中,为了能够加快Web...

    ThreadLocal跨线程问题

    1、问题 通常复杂的处理流程中,我们会使用一些异步处理的手段,... ThreadLocal threadLocal = new ThreadLocal(); threadLocal.set("A"); System.out.println(Thread.currentThread().getName()+"-getThreadLocal:

    Java中的线程同步与ThreadLocal无锁化线程封闭实现

    主要介绍了Java中的线程同步与ThreadLocal无锁化线程封闭实现,Synchronized关键字与ThreadLocal变量的使用是Java中线程控制的基础,需要的朋友可以参考下

    java事务 - threadlocal

    ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量

    java线程本地变量ThreadLocal详解

    ThreadLocal则为每一个线程提供了一个变量副本,从而隔离了多个线程访问数据的冲突,ThreadLocal提供了线程安全的对象封装,下面我们就来详细了解一下吧

    使用Java ThreadLocal.docx

    虽然所有的线程都能访问到这个ThreadLocal实例,但是每个线程却只能访问到自己通过调用ThreadLocal的set()方法设置的值。即使是两个不同的线程在同一个ThreadLocal对象上设置了不同的值,他们仍然无法访问到对方的值...

    ThreadLocal 线程本地变量 及 源码分析.rar_开发_设计

    ThreadLocal 线程微本地变量 及 源码分析

    ThreadLocal源码分析

    首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。

Global site tag (gtag.js) - Google Analytics