工作要求用Java了,有很多东西要学习.不得不暂时告别一下.net
在看Spring的时候突然想到.net里面的ThreadStaticAttribute(允许static变量在不同线程不同).
在很多情况下每个执行线程里面的内容是固定的,比如web环境下servlet的CurrentUser/HttpContext/Session.很多情况下这些变量被想方设法的传递到后层类中,造成设计的复杂.
.net中很好的设计方法就是Static: Thread.CurrentPrincipal / HttpContext.Current ....
那么Java中是否也有类似机制呢?答案是ThreadLocal.
API doc: http://java.sun.com/j2se/1.4.2/docs/api/index.html
DW上Brian Goetz 的文章:http://www-900.ibm.com/developerWorks/cn/java/j-threads/index3.shtml
Brian Goetz 在文章中指出,在jdk1.4中ThreadLocal的性能已经可以不用担心.
在用法上比.net要复杂,API中的例子比较怪异,这里是我自己写的例子:
结果:
看样ThreadLocal工作的很好.请注意ThreadLocal类似一个访问媒介,get()返回的值是存储在当前线程中的.
值得注意的是InheritableThreadLocal类,可以使ThreadLocal数据传递到子线程中.
另外servlet线程可能会被重新利用,要注意在每个servlet开始时重新初始化.
在看Spring的时候突然想到.net里面的ThreadStaticAttribute(允许static变量在不同线程不同).
在很多情况下每个执行线程里面的内容是固定的,比如web环境下servlet的CurrentUser/HttpContext/Session.很多情况下这些变量被想方设法的传递到后层类中,造成设计的复杂.
.net中很好的设计方法就是Static: Thread.CurrentPrincipal / HttpContext.Current ....
那么Java中是否也有类似机制呢?答案是ThreadLocal.
API doc: http://java.sun.com/j2se/1.4.2/docs/api/index.html
DW上Brian Goetz 的文章:http://www-900.ibm.com/developerWorks/cn/java/j-threads/index3.shtml
Brian Goetz 在文章中指出,在jdk1.4中ThreadLocal的性能已经可以不用担心.
在用法上比.net要复杂,API中的例子比较怪异,这里是我自己写的例子:
public class Hello implements Runnable{
static class Counter{
int c = 0;
public void Count(){
System.out.println(Thread.currentThread().hashCode() + ": "+ c++);
}
}
private static ThreadLocal counter = new ThreadLocal(){
protected Object initialValue() {return new Counter();}
};
public static Counter Counter(){return (Counter)counter.get();}
public static void main(String[] args)throws Exception {
Hello h = new Hello();
h.run();
new Thread(new Hello()).start();
Thread.sleep(1000L);
h.run();
Counter().Count();
}
public void run() {
Counter().Count();
Counter().Count();
Counter().Count();
}
}
static class Counter{
int c = 0;
public void Count(){
System.out.println(Thread.currentThread().hashCode() + ": "+ c++);
}
}
private static ThreadLocal counter = new ThreadLocal(){
protected Object initialValue() {return new Counter();}
};
public static Counter Counter(){return (Counter)counter.get();}
public static void main(String[] args)throws Exception {
Hello h = new Hello();
h.run();
new Thread(new Hello()).start();
Thread.sleep(1000L);
h.run();
Counter().Count();
}
public void run() {
Counter().Count();
Counter().Count();
Counter().Count();
}
}
结果:
25358555: 0
25358555: 1
25358555: 2
26399554: 0
26399554: 1
26399554: 2
25358555: 3
25358555: 4
25358555: 5
25358555: 6
25358555: 1
25358555: 2
26399554: 0
26399554: 1
26399554: 2
25358555: 3
25358555: 4
25358555: 5
25358555: 6
看样ThreadLocal工作的很好.请注意ThreadLocal类似一个访问媒介,get()返回的值是存储在当前线程中的.
值得注意的是InheritableThreadLocal类,可以使ThreadLocal数据传递到子线程中.
另外servlet线程可能会被重新利用,要注意在每个servlet开始时重新初始化.