线程变量ThreadLocal

0.前言

 

首先该会话共享本身就是一个属于多个系统进行数据交互的工具包.而不同系统间都会通过一个个页面请求经过该会话共享来完成各自的数据传输.所以这就要求每个系统的页面请求都是一个独立的,也就是线程保护的页面请求.

 

而对浏览器进行操作需要用到HttpServletRequest,和 HttpServletResponse.在该会话共享中,用到了线程变量ThreadLocal来存储 HttpServletRequest,和 HttpServletResponse.

那么首先,我们需要了解什么是线程变量,这里我就贴上了网上的案例囖,再加上自己的一些见解.

 

1.什么是线程变量?

 

ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

 

 
从线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。
 
通过ThreadLocal存取的数据,总是与当前线程相关,也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出现的并发访问问题提供了一种隔离机制。
 
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。
 
概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
 
用我自己的理解就是,线程可以让每一个线程都保留有自己的一份变量,而不受其他线程的影响,A线程存储的值,在A线程开始到结束之间的任意一个时间段拿出来的都会是存储的值,这就是我的理解,线程间互不影响.
 
当时提出这个想法的人是我的manager,因为这边的会话共享是需要用到requst和response的,通过Filter一层层传下去也不是不可以,就是代码写得很乱,后来提出了用线程变量,感觉到有耳目一新的感觉.
 
 2.API
 
ThreadLocal()  创建一个线程本地变量。
 
T get()   返回此线程局部变量的当前线程副本中的值,如果这是线程第一次调用该方法,则创建并初始化此副本。
 
protected  T initialValue()   返回此线程局部变量的当前线程的初始值。最多在每次访问线程来获得每个线程局部变量时调用此方法一次,即线程第一次使用 get() 方法访问变量的时候。如果线程先于 get 方法调用 set(T) 方法,则不会在线程中再调用 initialValue 方法。
    若该实现只返回 null;如果程序员希望将线程局部变量初始化为 null 以外的某个值,则必须为 ThreadLocal 创建子类,并重写此方法。通常,将使用匿名内部类。initialValue 的典型实现将调用一个适当的构造方法,并返回新构造的对象。
 
void remove()    移除此线程局部变量的值。这可能有助于减少线程局部变量的存储需求。如果再次访问此线程局部变量,那么在默认情况下它将拥有其 initialValue。
 
void set(T value)     将此线程局部变量的当前线程副本中的值设置为指定值。许多应用程序不需要这项功能,它们只依赖于 initialValue() 方法来设置线程局部变量的值。程序中一般都重写initialValue方法,以给定一个特定的初始值。
 
3.实现代码块
 
package com.citicpru.framework.sessionSharingPlatform.web;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 通过拦截器获取中间件所需的request和response
 * 
 * @author INGO
 * @date 2017-6-6 Copyright (c) 2008, 2010 Citicpru insurance company All Rights
 *       Reserved.
 */
public class WebContextHolder {

    private final static String REQUEST = "REQUEST";
    private final static String RESPONSE = "RESPONSE";
    private final static String SESSIONID = "SESSIONID";
    private final static String CONTEXT = "CONTEXT";
    private final static String SESSIONMAP = "SESSIONMAP";

    // 创建一个Integer型的线程本地变量
    private static final ThreadLocal<HashMap<String, Object>> local = new ThreadLocal<HashMap<String, Object>>() {
        @Override
        protected HashMap<String, Object> initialValue() {
            return new HashMap<>();
        }
    };
    
    public static void ResetSessionMap() {
        HashMap<String, Object> localHashmap = local.get();
        localHashmap.put(SESSIONMAP, new HashMap<String, Object>());
    }

    public static void setRequest(HttpServletRequest request) {
        HashMap<String, Object> localHashmap = local.get();
        localHashmap.put(REQUEST, request);
    }

    public static void setResponse(HttpServletResponse response) {
        HashMap<String, Object> localHashmap = local.get();
        localHashmap.put(RESPONSE, response);
    }

    public static void setSessionid(String sessionid) {
        HashMap<String, Object> localHashmap = local.get();
        localHashmap.put(SESSIONID, sessionid);
    }

    public static void setServletContext(ServletContext context) {
        HashMap<String, Object> localHashmap = local.get();
        localHashmap.put(CONTEXT, context);
    }

    public static void setSessionMap(Map<String, Object> sessionMap) {
        HashMap<String, Object> localHashmap = local.get();
        localHashmap.put(SESSIONMAP, sessionMap);
    }

    public static HttpServletRequest getRequest() {
        HashMap<String, Object> localHashmap = local.get();
        Object objRequest = localHashmap.get(REQUEST);
        return objRequest != null ? (HttpServletRequest) objRequest : null;
    }

    public static HttpServletResponse getResponse() {
        HashMap<String, Object> localHashmap = local.get();
        Object objResponse = localHashmap.get(RESPONSE);
        return objResponse != null ? (HttpServletResponse) objResponse : null;
    }

    public static String getSessionid() {
        HashMap<String, Object> localHashmap = local.get();
        Object objSessionid = localHashmap.get(SESSIONID);
        return objSessionid != null ? (String) objSessionid : null;
    }

    public static ServletContext getServletContext() {
        HashMap<String, Object> localHashmap = local.get();
        Object objFilePath = localHashmap.get(CONTEXT);
        return objFilePath != null ? (ServletContext) objFilePath : null;
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> getSessionMap() {
        HashMap<String, Object> localHashmap = local.get();
        Object objSessionMap = localHashmap.get(SESSIONMAP);
        return objSessionMap != null ? (HashMap<String, Object>) objSessionMap : null;
    }

    public static Object getSessionAttribute(String key) {
        Map<String, Object> sessionMap = getSessionMap();
        if (sessionMap == null)
            return null;

        return sessionMap.get(key);

    }
}
View Code

 

 
posted @ 2017-12-07 18:14  IngoKeepGoing  阅读(755)  评论(0)    收藏  举报