线程封闭

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();
    }
}

 

 

以上是关于线程封闭的主要内容,如果未能解决你的问题,请参考以下文章

线程封闭

并发编程-线程安全策略之线程封闭

Java多线程——线程封闭

Java多线程——线程封闭

Java并发编程:线程封闭--ThreadLocal

线程封闭