002ThreadLocal概念

        ThreadLocal线程局部变量,是一种多线程间并发访问变量的解决方案。与其synchronized等加锁的方式不同,ThreadLocal完全不提供锁,而使用以空间换时间的手段,为每个线程提供变量的独立副本,以保障线程安全。

        从性能上说,ThreadLocal不具有绝对的优势,在并发不是很高的时候,加锁的性能会更好,但作为一套与锁完全无关的线程安全解决方案,在高并发量或者竞争激烈的场景,使用ThreadLocal可以在一定程度上减少锁竞争。

模拟:ThreadLocal的值是跟着线程走,下列代码中,共有三个线程,对同一个对象UseTreadLocal操作,主线程没有set所以为null,线程t1调用set方法存入“张三”,在t1线程中get值即为张三,线程t2调用set存入“李四”,那么t2线程get值为“李四”。

public class UseTreadLocal {
    
    public static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public  String getThreadLocal() {
        return threadLocal.get();
    }

    public void setThreadLocal(String value) {
        threadLocal.set(value);;
    }
    
    public static void main(String[] args) {
        
        UseTreadLocal utl = new UseTreadLocal();
        
        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                utl.setThreadLocal("张三");
                System.out.println("当前t1:"+utl.getThreadLocal());
            }
            
        },"t1");
        
        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    //Thread.sleep(1000);
                    utl.setThreadLocal("李四");
                    System.out.println("当前t2:"+utl.getThreadLocal());
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
            
        },"t2");
        
        t1.start();
        t2.start();
        System.out.println("当前主线程:"+utl.getThreadLocal());
    }

}

 

 

/*
 * 模拟统一提交场景,当前线程执行完毕后再提交
 */

public class MessageHolder {
    //创建容器对象,messages是一个集合,可以盛装消息
    private List<String> messages = new ArrayList<>();
    //创建ThreadLocal线程队列,并重写ThreadLocal的initialValue
    public static final ThreadLocal<MessageHolder> holder = new ThreadLocal() {
        /*
         * 重写方法,并将MessageHolder在初始化的时候创建出来,
         * 获取时就不会为null,即预加载机制
         */
        @Override
        protected Object initialValue() {
            return new MessageHolder();
        }
    };
    
    public static void add(String message) {
        holder.get().messages.add(message);
    }
    
    public static List<String> clear(){
        List<String> result = holder.get().messages;
        holder.remove();
        System.out.println("size:" + holder.get().messages.size());
        return result;
    }
    
    public static void main(String[] args) {
        
        MessageHolder.add("11111");
        MessageHolder.add("22222");
        MessageHolder.add("33333");
        MessageHolder.add("44444");
        MessageHolder.add("55555");
        
        List<String> result = MessageHolder.clear();
        System.out.println(result.toString());
    }

}

知识点:
1.ThreadLocal应用场景,使用的是空间换时间的策略,为每个线程提供独立的副本进行数据存储;
2.从性能上说ThreadLocal不具有绝对的优势,在并发不是很高的时候,加synchronized锁的性能会更好,但是作为一套与锁完全无关的线程安全解决方案,在高并发量或者竞争激烈场景,使用ThreadLocal可以在一定程度上减少锁竞争。

 

例如场景:线程A执行m1方法后得到1,2然后要带着1,2执行m2方法,获得3,4,在带着数据执行m3方法,获得5,6,最后将1,2,3,4,5,6所有数据全部返还给线程A,并且执行的同时不影响其他线程执行方法。


/*传统实现方法必须加synchronized锁
 * public synchronized allmethod(){
 *         return 1,2 = m1();
 *         return 3,4 = m2();
 *         return 5,6 = m3();
 * 
 *         all return 123456;
 * }
 * 
 */

知识点:

ThreadLocal针对线程提供一个放置元素的副本,设置的数据只是针对单独的线程;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值