线程封闭
Posted lishuaiqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程封闭相关的知识,希望对你有一定的参考价值。
1.jdbc和servlet的例子
jdbc和servlet中,之所以是线程安全的,就是因为每个变量都封装在单个线程中,不会存在变量共享的状态,也就是说,你这一次获取的数据不会被下一个请求访问到,所以通过把变量都封闭在线程中,来达到了线程安全的目的.所以在servlet中使用 缓存 session 或者定义 static 等共享变量的时候就要小心,因为这些是多个线程所共享的,所以需要保证线程安全问题.
2.栈封闭
局部变量都封闭在执行线程中,只要不发布局部变量,就没有线程安全问题.
public class SafeClass { public int safeMethod(Collection<String> collection) { //i被封装在的栈中,具体参考<深入理解java虚拟机> //i因为被封装在栈中,不会被别的线程访问到,所以也就保证了线程安全 int i = 0; i++; //sortedSet 同理,也被封闭在栈中,没有逸出,也不会被别的线程访问到 SortedSet<String> sortedSet = new TreeSet<String>(); sortedSet.addAll(collection); return i; } }
3.ThreadLocal类
ThreadLocal能使线程中的值和保存值的对象关联起来,比如
package demo04; import java.util.concurrent.TimeUnit; public class ThreadLocalTest { public static void main(String[] args) { ThreadLocal<String> threadLocal = new ThreadLocal<String>(); Thread t1 = new Thread(() -> {threadLocal.set("t1"); System.out.println(threadLocal.get());}); Thread t2 = new Thread(() -> {threadLocal.set("t2"); System.out.println(threadLocal.get());}); t1.start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t2.start(); //结果为: //t1 //t2 } }
t1 和 t2 中线程用相同的ThreadLocal保存值,但是在通过 get() 方法获取值的时候,只会返回之前在该线程 set() 方法设置的值,不会返回别的线程的值,相当于一个独立的副本.
用jdbc举例子,在一个线程中,我们需要调用很多方法,但是每个方法都传入不同的Connection会有线程安全问题,所以我们可以把 Connection 封装在ThreadLocal中,来为每个线程创建一个全局变量.
通过ThreadLocal类,我们可以为每个线程创建属于自己的 Connection,代码如下:
public class ConnectionHolderTest { //new ThreadLocal<T>(){} //大括号中 {} 的意思表示每次调用get方法都会执行 initialValue这个方法. private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>(){ public Connection initialValue() { try { return DriverManager.getConnection(""); } catch (SQLException e) { e.printStackTrace(); return null; } } }; public static Connection getConnection() { return connectionHolder.get(); } }
以上是关于线程封闭的主要内容,如果未能解决你的问题,请参考以下文章