一直无知的以为线程安全只有用上锁,wait(),sleep(),notify(),notifyAll()来解决,现在才知道还有个ThreadLocal这个东西~~~
我以前以为线程安全都是在线程上做文章,一个线程访问一个资源,只有等这个线程执行完毕下一个线程才能去访问。
而ThreadLocal这个类是为每个线程提供独立的变量副本,多个线程同时访问一个变量,is ok的,因为每个线程都可以独立的改变自己的变量副本,而不改变其它的,所以互不影响。
这个类jdk5后有4个方法
void set(Object value);//设置当前线程的线程局部变量的值
public Object get();//得到当前线程的局部变量的值
protected Object initialValue();//返回该局部变量的初始值
因为是protected的方法,也就是让子类覆盖重写的方法
public void remove();//将当前线程局部变量的值删除,目的是减少内存的占用。当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显示调用该方法是为了加快内存回收的速度。
ThreadLocalMap现在不写,没有为什么,因为任性。(手动微笑)
//例子一
package testEpcc;
public class TestThreadLocal {
//通过匿名内部类覆盖ThreadLocal的initalValue方法
private static ThreadLocal<Integer> tl=new ThreadLocal<Integer>(){
public Integer initialValue(){
return 0;
}
};
//获取下一个序列值
public int getNext(){
tl.set(tl.get()+1);
return tl.get();
}
public static void main(String[] args) {
TestThreadLocal l=new TestThreadLocal();
Thread t1=new Thread(new TestThead(l));
Thread t2=new Thread(new TestThead(l));
Thread t3=new Thread(new TestThead(l));
t1.start();
t2.start();
t3.start();
}
}
package testEpcc;
public class TestThead implements Runnable {
private TestThreadLocal local;
public TestThead(TestThreadLocal local) {
super();
this.local = local;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+"进行第"+local.getNext()+"个。");
}
}
}
//例子二
package testEpcc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestConDao {
private static ThreadLocal<Connection> connectionHolder=new ThreadLocal<Connection>(){
@Override
protected Connection initialValue() {
// TODO Auto-generated method stub
Connection con=null;
try {
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/test","epcc","epcc");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return con;
}
};
public void setConn(Connection con){
connectionHolder.set(con);
}
public Connection getConnection(){
return connectionHolder.get();
}
}