ThreadLocal模式探索
一、首先,ThreadLocal模式使共享数据能多个线程被访问,每个线程访问的只是这个数据的副本,线程之间互不影响。
例子1:
package Thread2; public class Counter { //新建一个静态的ThreadLocal变量,并通过get方法将其变为一个可访问的对象 private static ThreadLocal<Integer> counterContext = new ThreadLocal<Integer>(){ protected synchronized Integer initialValue(){ return 10; } }; //通过静态的get方法访问ThreadLocal中存储的值 public static Integer get(){ return counterContext.get(); } //通过静态的set方法将变量值设置到ThreadLocal中 public static void set (Integer value){ counterContext.set(value); } //封装业务逻辑,操作存储于ThreadLocal中的变量 public static Integer getNextCounter(){ counterContext.set(counterContext.get()+1); return counterContext.get(); } }
package Thread2; public class ThreadLocalTest extends Thread { public void run(){ for(int i = 0; i < 3; i ++){ System.out.println("Thread[" + Thread.currentThread().getName() + " ], " + "counter = " + Counter.getNextCounter()); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package Thread2; public class Test2 { public static void main(String[] args) throws Exception{ ThreadLocalTest testThread1 = new ThreadLocalTest(); ThreadLocalTest testThread2 = new ThreadLocalTest(); ThreadLocalTest testThread3 = new ThreadLocalTest(); testThread1.start(); testThread2.start(); testThread3.start(); } }
运行结果:
Thread[Thread-2 ], counter = 11
Thread[Thread-0 ], counter = 11
Thread[Thread-1 ], counter = 11
Thread[Thread-1 ], counter = 12
Thread[Thread-2 ], counter = 12
Thread[Thread-0 ], counter = 12
Thread[Thread-2 ], counter = 13
Thread[Thread-1 ], counter = 13
Thread[Thread-0 ], counter = 13
例子2:
package Thread; class AStub { public void output() { LocalThreadScopeData data = LocalThreadScopeData.getInstance(); if (data != null) System.out.println("AStub:" + Thread.currentThread().getName() + ": data name = " + data.getName() + "age= " + data.getAge()); } } package Thread; class BStub { public void output() { LocalThreadScopeData data = LocalThreadScopeData.getInstance(); if (data != null) System.out.println("BStub:" + Thread.currentThread().getName() + ": data name = " + data.getName() + "age= " + data.getAge()); } } package Thread; class LocalThreadScopeData { // 把对象与当前线程绑定 private static ThreadLocal<LocalThreadScopeData> mThreadLocal = new ThreadLocal<LocalThreadScopeData>(); // 当前实例 private static LocalThreadScopeData instance = null; // 单例模式 public static LocalThreadScopeData getInstance() { instance = mThreadLocal.get(); if (instance == null) { instance = new LocalThreadScopeData(); mThreadLocal.set(instance); } return instance; } private String name;// 姓名 private Integer age;// 年龄 public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } package Thread; import java.util.Random; public class ThreadTest { public static void main(String argv[]) { // 启动俩个线程 for (int i = 0; i < 2; i++) { new Thread() { public void run() { int value = new Random().nextInt(10); LocalThreadScopeData data = LocalThreadScopeData .getInstance(); data.setAge(value); data.setName("name" + value); System.out.println("main:" + Thread.currentThread().getName() + "name = name " + value); try { Thread.sleep(1000); } catch (InterruptedException e) { } new AStub().output(); new BStub().output(); } }.start(); } } }
运行结果:
main:Thread-0name = name 5
main:Thread-1name = name 0
AStub:Thread-0: data name = nullage= null
AStub:Thread-1: data name = name0age= 5
BStub:Thread-0: data name = nullage= null
BStub:Thread-1: data name = name0age= 5
例子3:
package Thread4; public class Student { private int age = 0; //年龄 public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } } package Thread4; import java.util.Random; public class ThreadLocalDemo implements Runnable { //创建线程局部变量studentLocal,在后面你会发现用来保存Student对象 private final static ThreadLocal studentLocal = new ThreadLocal(); public static void main(String[] agrs) { ThreadLocalDemo td = new ThreadLocalDemo(); Thread t1 = new Thread(td, "a"); Thread t2 = new Thread(td, "b"); t1.start(); t2.start(); } public void run() { accessStudent(); } /** * 示例业务方法,用来测试 */ public void accessStudent() { //获取当前线程的名字 String currentThreadName = Thread.currentThread().getName(); System.out.println(currentThreadName + " is running!"); //产生一个随机数并打印 Random random = new Random(); int age = random.nextInt(100); System.out.println("thread " + currentThreadName + " set age to:" + age); //获取一个Student对象,并将随机数年龄插入到对象属性中 Student student = getStudent(); student.setAge(age); System.out.println("thread " + currentThreadName + " first read age is:" + student.getAge()); try { Thread.sleep(500); } catch (InterruptedException ex) { ex.printStackTrace(); } System.out.println("thread " + currentThreadName + " second read age is:" + student.getAge()); } protected Student getStudent() { //获取本地线程变量并强制转换为Student类型 Student student = (Student) studentLocal.get(); //线程首次执行此方法的时候,studentLocal.get()肯定为null if (student == null) { //创建一个Student对象,并保存到本地线程变量studentLocal中 student = new Student(); studentLocal.set(student); } return student; } }
运行结果:
b is running!
thread b set age to:31
a is running!
thread a set age to:45
thread b first read age is:31
thread a first read age is:45
thread b second read age is:31
thread a second read age is:45
参考:struts2设计模式,
http://lavasoft.blog.51cto.com/62575/51926/
http://blog.csdn.net/com360/article/details/6789367