关于ThreadLocal
<参考一>
首先有几点需要大家清楚的:
1、 ThreadLocal只是对需要存储的对象的管理,而存储实际是由当前Thread负责。个人理解为ThreadLocal是一个操作Thread. threadLocals 的工具。
2、 使用ThreadLocal可以使对象达到线程隔离的目的。同一个ThreadLocal操作不同的Thread,实质是各个Thread对自己的变量操作。
3、 为什么要使用ThreadLocal,个人感觉有两个原因,1是与其它线程的隔离,2是可以在一个线程的生命周期中使用同一个对象,达到对象传递的作用。这样的好处是可以减少dal访问或者ws调用。
我这里列出一个用到ThreadLocal的例子,主要的作用是使用ThreadLocal记录用户信息以及记录用户的执行时间。这在实际应用中,可以映射为全局记录用户的权限,以及使用Threadlocal对系统的性能做一些分析等。。
首先有两个对象,一个是用户对象
// 简单记录用户是否可以访问,可以用于全局权限控制等 class User { private String name; private boolean isAllow; public User(String name, boolean isAllow) { this.name = name; this.isAllow = isAllow; } public String getName() { return name; } public boolean isAllow() { return isAllow; } @Override public String toString() { return "用户名:" + name + "\t 是否允许访问:" + isAllow; } }
另一个是消费时间对象
// 用于记录每一步骤耗时…,可以用于每一步的性能分析 class TimeConsumer { // 名称 private String name; // 耗时数据列表 private List<Long> steps; public TimeConsumer(String name, long start) { this.name = name; steps = new ArrayList<Long>(); steps.add(start); } public void andStep(long step) { steps.add(step); } @Override public String toString() { StringBuffer br = new StringBuffer("操作[" + name + "]共有" + (steps.size() - 1) + "步\n"); for (int i = 1; i < steps.size(); i++) { br.append("\t|--耗时[" + (steps.get(i) - steps.get(0)) + "ms]\n"); } br.append("\n"); return br.toString(); } }
接下来,建立一个对这两个对象管理的ThreadLocal的类
// threadlocal 管理类 class MyThreadLocal { // 用于全局记录user访问权限 private ThreadLocal<User> userLocal; // 用于全局记录用户每一步的耗时 private ThreadLocal<TimeConsumer> timeLocal; private static MyThreadLocal local = new MyThreadLocal(); private MyThreadLocal() { userLocal = new ThreadLocal<User>(); timeLocal = new ThreadLocal<TimeConsumer>(); } public static MyThreadLocal getInstanse() { return local; } public void addUser(User user) { userLocal.set(user); } public User getUser() { return userLocal.get(); } public void addTime(TimeConsumer timeConsumer) { timeLocal.set(timeConsumer); } public void addTime(long l) { TimeConsumer time = timeLocal.get(); timeLocal.remove(); time.andStep(l); timeLocal.set(time); } public TimeConsumer getTime() { return timeLocal.get(); } }
接下来就可以对Threadlocal进行测试了。为了模拟多线程,我这里自己实现了多线程
public class CoreThreadLocal { public static void main(String[] args) { new Thread(new TestRunnable("name1", 1000L, true)).start(); new Thread(new TestRunnable("name2", 700L, true)).start(); new Thread(new TestRunnable("name3", 888, false)).start(); } } // 用于测试,多线程实现 class TestRunnable implements Runnable { String name; long l; boolean isAllow; TestRunnable(String name, long l, boolean isAllow) { this.name = name; this.l = l; this.isAllow = isAllow; } public void run() { MyThreadLocal local = MyThreadLocal.getInstanse(); local.addUser(new User(name, isAllow)); local.addTime(new TimeConsumer(name, System.currentTimeMillis())); // 做某个业务,并记录时间 doThings(l); local.addTime(System.currentTimeMillis()); // 做某个业务,并记录时间 doThings(l); local.addTime(System.currentTimeMillis()); // 业务做完,打印日志 System.out.println(local.getUser()); System.out.println(local.getTime()); } // 模拟具体业务的处理步骤 private void doThings(long l) { try { Thread.sleep(l); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行上面的程序得到结果如下:

浙公网安备 33010602011771号