zoukankan      html  css  js  c++  java
  • Java ThreadLocal示例及使用方法总结

    一、概述

    ThreadLocal的名称比较容易让人误解,会认为其是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量。

    其设计的初衷是为了解决多线程编程中的资源共享问题。提起这个,大家一般会想到synchronized,synchronized采取的是“以时间换空间”的策略,本质上是对关键资源上锁,让大家排队操作。而ThreadLocal采取的是“以空间换时间”的思路,为每个使用该变量的线程提供独立的变量副本,在本线程内部,它相当于一个“全局变量”,可以保证本线程任何时间操纵的都是同一个对象。

     二、实例

    下面用一个实例阐述ThreadLocal的使用方法

    创建一个Context类,其中含有transactionId属性。 

     1 package com.vigar;
    2
    3 public class Context {
    4
    5 private String transactionId = null;
    6
    7 public String getTransactionId() {
    8 return transactionId;
    9 }
    10
    11 public void setTransactionId(String transactionId) {
    12 this.transactionId = transactionId;
    13 }
    14 }

    创建MyThreadLocal做为容器,将一个Context对象保存于ThreadLocal中

     1 package com.vigar;
    2
    3 public class MyThreadLocal {
    4 public static final ThreadLocal userThreadLocal = new ThreadLocal();
    5 public static void set(Context user) {
    6 userThreadLocal.set(user);
    7 }
    8
    9 public static void unset() {
    10 userThreadLocal.remove();
    11 }
    12
    13 public static Context get() {
    14 return (Context)userThreadLocal.get();
    15 }
    16 }

    多线程客户端程序,用于测试

     1 package com.vigar;
    2
    3 import java.util.Random;
    4
    5 public class ThreadLocalDemo extends Thread {
    6
    7 public static void main(String[] args) {
    8 Thread threadOne = new ThreadLocalDemo();
    9 threadOne.start();
    10 Thread threadTwo = new ThreadLocalDemo();
    11 threadTwo.start();
    12 }
    13
    14 @Override
    15 public void run() {
    16 // 线程
    17 Context context = new Context();
    18 Random random = new Random();
    19 int age = random.nextInt(100);
    20 context.setTransactionId(String.valueOf(age));
    21
    22 System.out.println("set thread ["+getName()+"] contextid to " + String.valueOf(age));
    23 // 在ThreadLocal中设置context
    24 MyThreadLocal.set(context);
    25 /* note that we are not explicitly passing the transaction id */
    26 try {
    27 Thread.sleep(1000);
    28 } catch (InterruptedException e)
    29 {
    30 e.printStackTrace();
    31 }
    32
    33 new BusinessService().businessMethod();
    34 MyThreadLocal.unset();
    35 }
    36 }

    模拟业务层,在某处读取context对象

    1 package com.vigar;
    2 public class BusinessService {
    3 public void businessMethod() {
    4 Context context = MyThreadLocal.get();
    5 System.out.println(context.getTransactionId());
    6 }
    7 }

    程序输出:

    set thread [Thread-0] contextid to 32
    set thread [Thread-1] contextid to 89
    32
    89

    三、总结
    ThreadLocal使用步骤

    1.建立ThreadLocal容器对象A,其中对需要保存的属性进行封装。并提供相应的get/set方法(全部为static)

    2.在客户端程序中,用A.setxxx, A.getXXX访问相应数据,即可保证每个线程访问的是自己独立的变量

    
    

     参考文献:

     1. http://lavasoft.blog.51cto.com/62575/51926/

     2. http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/

  • 相关阅读:
    详解Android Intent
    【JAVA EE企业级开发四步走完全攻略】
    撼动IT界的10大编程语言
    System.getProperty() 常用值
    Android List,Adapter相关
    为程序员量身定制的12个目标
    java 算法数据
    JAVA基础之理解JNI原理
    Java 工厂模式
    linux下C语言读取网卡MAC地址
  • 原文地址:https://www.cnblogs.com/vigarbuaa/p/2375149.html
Copyright © 2011-2022 走看看