1. 程式人生 > >簡單的上下文讀寫Context實現

簡單的上下文讀寫Context實現

Context上下文主要用來從上文傳播物件到下文中,他是可以跨執行緒的。 就是說 class A中你把一個OBJ物件存放到了上下文容器中, 然後你以後的所有執行緒或你以下呼叫的所有類中都可以從上下文容器中取出 上面再class A中存放的OBJ物件。而ThreadLocal對上下文的讀寫至關重要。

ThreadLocal用於儲存某個執行緒共享變數:對於同一個static ThreadLocal,不同執行緒只能從中get,set,remove自己的變數,而不會影響其他執行緒的變數。

1、ThreadLocal.get: 獲取ThreadLocal中當前執行緒共享變數的值。

2、ThreadLocal.set: 設定ThreadLocal中當前執行緒共享變數的值。

3、ThreadLocal.remove: 移除ThreadLocal中當前執行緒共享變數的值。

4、ThreadLocal.initialValue: ThreadLocal沒有被當前執行緒賦值時或當前執行緒剛呼叫remove方法後呼叫get方法,返回此方法值。

程式碼實現:
Context.java

package com.gm.context;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 讀寫上下文
 * @author gm
 *
 */
public class Context implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private static Logger logger = LoggerFactory.getLogger(Context.class);
	
	private Map<String, Object> map = new HashMap<String, Object>();
	
	
	public static Context getInstance() {
		Stack contexts = getContextStack();
		if (contexts.empty()) {
			contexts.push(new Context());
			logger.info("Pressing context into context stack!");
		}
		//相同點:大家都返回棧頂的值。不同點:peek 不改變棧的值(不刪除棧頂的值),pop會把棧頂的值刪除。
		return (Context) contexts.peek();
	}
	
	/**
	 * 獲取上下文棧
	 * @return
	 */
	private static Stack<Context> getContextStack() {
		Stack contexts = (Stack) ThreadLocalManager.getTranContext();
		if (null == contexts) {
			contexts = new Stack();
			ThreadLocalManager.setTranContext(contexts);
			logger.info("Create a stack and fill in ThreadLocal!");
		}
		return contexts;
	}

	public Object getObject(String key) {
		return this.map.get(key);
	}

	public void setObject(String key, Object value) {
		this.map.put(key, value);
	}

}

ThreadLocal編寫
ThreadLocalManager.java

package com.gm.context;

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

/**
 * ThreadLocal管理類
 * @author gm
 *
 */
public class ThreadLocalManager {
	/*
	 * ThreadLocal用於儲存某個執行緒共享變數:對於同一個static ThreadLocal,不同執行緒只能從中get,set,remove自己的變數,而不會影響其他執行緒的變數。
	 * 1、ThreadLocal.get: 獲取ThreadLocal中當前執行緒共享變數的值。
	 * 2、ThreadLocal.set: 設定ThreadLocal中當前執行緒共享變數的值。
	 * 3、ThreadLocal.remove: 移除ThreadLocal中當前執行緒共享變數的值。
	 * 4、ThreadLocal.initialValue: ThreadLocal沒有被當前執行緒賦值時或當前執行緒剛呼叫remove方法後呼叫get方法
	 */
	public static ThreadLocal<Map<String, Object>> LOCAL = new ThreadLocal<Map<String, Object>>() {
		protected Map<String, Object> initialValue() {
			return new HashMap<String, Object>();
		}
	};
	public static final String GM_UID_KEY = "GM_UID";
	public static final String TRAN_CONTEXT_KEY = "TRAN_CONTEXT";


	public static <T> void setTranContext(T tranContext) {
		((Map<String, Object>) LOCAL.get()).put(TRAN_CONTEXT_KEY, tranContext);
	}

	public static <T> T getTranContext() {
		return (T) ((Map) LOCAL.get()).get(TRAN_CONTEXT_KEY);
	}

	public static void put(String key, Object vlaue) {
		((Map<String, Object>) LOCAL.get()).put(key, vlaue);
	}

	public static Object get(String key) {
		return ((Map<String, Object>) LOCAL.get()).get(key);
	}

	public static Map<String, Object> getALlInfo() {
		return (Map<String, Object>) LOCAL.get();
	}

	public static void remove() {
		LOCAL.remove();
	}
}

測試

package com.gm.context;

import java.util.ArrayList;
import java.util.List;


public class ContextTest {

	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		Context.getInstance().setObject("list", list);
		System.out.println(Context.getInstance().getObject("list"));
	}
}

執行後的日誌:
在這裡插入圖片描述