单例对象: 自始至终只有一个对象
当线程并发,每个线程需要自己独立的资源变量处理不同的业务时,单例对象远远不能满足需求
因此可以采用ThreadLocal模式 : 每个线程有自己独立的资源变量 而且每个线程的资源是独享的 其他线程不能访问和修改
笔者刚开始工作时候使用的Struts2,也曾略读过Struts2源码;就个人而言 虽然和现在对比已经过时,但是Struts2的设计思想还是很不错的,每个请求对应一个Action对象
也是ThreadLocal的代表,除去Struts2的标签和OGNL,整体性能也是不错的,读者有兴趣可以自己研究一下
单利模式:
//单例模式 私有构造 只有一个对象 public class Singleton{ private static Singleton instance = null; private Singleton(){} public synchronized static Singleton getInstance(){ if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
ThreadLocal模式
public class Struts2{ private static ThreadLocal<Struts2> map = new ThreadLocal<Struts2>(); private Struts2(){ } // synchronized不需要设置 每个线程享有自己独立资源 public static Struts2 getThreadInstance(){ Struts2 instance = map.get(); if(instance == null){ instance = new Struts2(); map.set(instance); } return instance; } //Strtus2就是这种设计思想 private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
//测试类
public class TestThreadLocal{ 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() + " has put data :" + data); Struts2.getThreadInstance().setMsg(data+""); //存数据 new UserA().get(); new UserB().get(); } }).start(); } } static class UserA{ public void get(){ Struts2 obj = Struts2.getThreadInstance(); System.out.println("UserB from " + Thread.currentThread().getName() + " 数据是 : "+obj.getMsg() ); } } static class UserB{ public void get(){ Struts2 obj = Struts2.getThreadInstance(); System.out.println("UserB from " + Thread.currentThread().getName() + " 数据是 : "+obj.getMsg() ); } } }
输出结果:
Thread-1 has put data :223586296
Thread-0 has put data :1184404572
UserB from Thread-0 数据是 : 1184404572
UserB from Thread-1 数据是 : 223586296
UserB from Thread-1 数据是 : 223586296
UserB from Thread-0 数据是 : 1184404572
备注:每个线程有只属于这个线程的对象,每个线程享有自己独立的副本,内部相当于一个Map key[当前线程] - vlaue[值], 线程结束后 会自动把结束的线程移除,不需要自己remove