1. 程式人生 > 實用技巧 >Java ThreadLocal示例及使用方法總結

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/