第三十四篇:JAVA中ThreadLocal用法介绍

概述

ThreadLocal看名字好像是一个Thread的实现,其实并不是这样的,ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。

线程局部变量其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

从线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。

API

构造方法摘要

方法名 说明
ThreadLocal() 创建一个线程本地变量

方法摘要

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

使用示例

import java.util.Random;

/**
 * ThreadLocal测试
 * 
 * @author jianggujin
 * 
 */
public class ThreadLocalDemo implements Runnable
{
   private final static ThreadLocal<People> threadLocal = new ThreadLocal<People>();

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

   public void run()
   {
      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);
      People people = getPeople();
      people.setAge(age);
      System.out.println("thread " + currentThreadName + " first read age is:"
            + people.getAge());
      try
      {
         Thread.sleep(500);
      }
      catch (InterruptedException ex)
      {
         ex.printStackTrace();
      }
      System.out.println("thread " + currentThreadName + " second read age is:"
            + people.getAge());
   }

   protected People getPeople()
   {
      People people = threadLocal.get();
      // 线程首次执行此方法的时候,threadLocal.get()肯定为null
      if (people == null)
      {
         // 创建一个对象,并保存到本地线程变量threadLocal中
         people = new People();
         threadLocal.set(people);
      }
      return people;
   }
}

class People
{
   private int age = 0;

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

   public void setAge(int age)
   {
      this.age = age;
   }
}
 
 
  • 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
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 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
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

总结

ThreadLocal使用场合主要解决多线程中数据数据因并发产生不一致问题。ThreadLocal为每个线程的中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果是耗费了内存,但是大大减少了线程同步所带来性能消耗(空间换时间),也减少了线程并发控制的复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值