zoukankan      html  css  js  c++  java
  • ThreadLocal

    import java.util.Random;

    /**
    * ThreadLocal类及应用技巧
    * *******************************************************************
    * 每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map中增加一条记录,key
    * 分别是各自的线程,values是各自的set方法穿进去的值。在线程结束时可以调用ThreadLocal.clear();
    * 方法,这样会更快释放内存,不调用也可以,因为线程结束后也可以自动释放相关的ThreadLocal变量。
    * 实现对ThreadLocal变量的封装,让外界不要直接操作ThreadLocal变量
    * 对基本类型的数据的封装,这种应用相对少见。
    * 对对象类型的数据的封装,比较常见,即让某个类针对不同线程分别创建一个独立的实例对象。
    * 总结:
    * 一个ThreadLocal代表一个变量,故其中里只能放一个数据,你有两个变量都要线程范围内
    * 共享,则要定义两个ThreadLocal对象。如果有一百个变量要线程共享呢?把ThreadLocal封装
    * 到一个单例类中。
    *
    * Struts2中的思想就是ThreadLocal模式
    *
    * *******************************************************************
    * 虚拟机挂掉的时候注册钩子通知
    * Runtime->addShutdownHook(Thread hook)
    * @author LiTaiQing
    */
    public class ThreadLocalTest {
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
    //private static ThreadLocal<MyThreadScopeData> myThreadScopeData = new ThreadLocal<MyThreadScopeData>();
    public static void main(String[] args){
    for(int i = 0; i < 2 ; i++){
    new Thread(new Runnable(){
    @Override
    public void run() {
    int data = new Random().nextInt();
    System.out.println(Thread.currentThread().getName() + " get put data :" + data);
    threadLocal.set(data);
    //myThreadScopeData.set(new MyThreadScopeData("name"+data,data));
    MyThreadScopeData.getThreadInstance().setName("name" + data);
    MyThreadScopeData.getThreadInstance().setAge(data);
    new A().get();
    new B().get();
    }
    }).start();
    }
    }
    static class A{
    public void get(){
    int data = threadLocal.get();
    System.out.println("A from" + Thread.currentThread().getName() + " get put data :" + data);
    //MyThreadScopeData myData = myThreadScopeData.get();
    MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
    System.out.println("A from" + Thread.currentThread().getName() + " getMyData :" + myData.getName()+","+myData.getAge());
    }
    }
    static class B{
    public void get(){
    int data = threadLocal.get();
    System.out.println("B from" + Thread.currentThread().getName() + " get put data :" + data);
    //MyThreadScopeData myData = myThreadScopeData.get();
    MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
    System.out.println("B from" + Thread.currentThread().getName() + " getMyData :" + myData.getName()+","+myData.getAge());
    }
    }
    }
    class MyThreadScopeData{
    private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();
    //private static MyThreadScopeData instance = null;//new MyThreadScopeData();

    private MyThreadScopeData(){};
    /**
    * 这里可以不用synchronized,因为位于不同的线程内分别保存在ThreadLocal中
    * @return
    */
    public static /*synchronized*/ MyThreadScopeData getThreadInstance(){
    MyThreadScopeData instance = map.get();
    //这种方式容易出现多线程并发问题。所以最好采用饿汉模式
    if(instance==null){
    instance = new MyThreadScopeData();
    map.set(instance);
    }
    return instance;
    }

    private String name;
    private int age;

    // public MyThreadScopeData(String name, int age) {
    // super();
    // this.name = name;
    // this.age = age;
    // }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    }

  • 相关阅读:
    java并发之hashmap源码
    java并发之hashmap
    java线程池之一:创建线程池的方法
    springAOP之代理模式
    java阻塞队列之LinkedBlockingQueue
    java阻塞队列之ArrayBlockingQueue
    java中的异常
    springboot入门之一:环境搭建(续)
    Unity 游戏框架搭建 2019 (二十三、二十四) 备份与版本号&危险的操作
    Unity 游戏框架搭建 2019 (二十一、二十二) 第三章简介&整理前的准备
  • 原文地址:https://www.cnblogs.com/hanwuxing/p/11413886.html
Copyright © 2011-2022 走看看