ThreadLocal

在开发中你可能关于遇到这样的场景:
1.在多线程的开发场景中,对于一些共享资源,且该共享资源不能保证线程安全,那么我们通常会给该资源进行加 锁的操作,如果加了锁,那么在并发情况下,并发线程在这就要进行排队了
2.同一个资源在涉及此次请求的每个方法都用到了,那么你可能会在每个方法出进行参收接受 对于上述情况,是否有个工具去解决? —ThreadLocal

引入:

典型场景1:每个线程需要一个独享的对象(通常是工具类,典型需要使用的类有SimpleDateFormat和Random)
典型场景2:每个线程内需要保存全局变量(例如在拦截器中获取用户信息),可以让不同方法直接使用,避免参数
传递的麻烦。
另外还用满足这样一种情况:不同线程有不同的业务对象,比如不同用户访问下单,装填购物车所需要的用户信息
不同,保证对象信息在线程之间的隔离
ConcurrentHashMap?
–底层是synchronized 影响性能
ThreadLocal?
–使用ThreadLocal 业务信息在同一线程内相同,但是在不同线程使用的业务内容是不同的。
–通过使用静态的ThreaLocal实例的get()方法可随时取出本线程需要的业务对象,同时避免了参数
相互传递的麻烦

对象独享

对于第一种开发场景
解决不同线程操作线程不安全的方法;其实为每一个线程去创建一个方法也可以避免多线程导致的冲突问题,但是面对大量的多线程并发,单独为每一个线程new 一个这样的方法显然是不合适的;可以为线程池中的每一个线程new出来,而不是运行一个线程 new 一个方法,采用ThreadLocal

public class ThreadLocalTest1 {

    public static  ExecutorService executorService = Executors.newFixedThreadPool(10);
    static Set<String> set = new HashSet();
    SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
    public static void main(String[] args) throws InterruptedException {
        ThreadLocalTest1 threadLocalTest1 = new ThreadLocalTest1();
        for (int i = 0; i < 1000; i++) {
            int finalI = i;
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    String date =  threadLocalTest1.date(Long.parseLong(String.valueOf(finalI)));
                    System.out.println(date);
                    set.add(date);
                }
            });
        }
        Thread.sleep(5000);
        System.out.println(set.size());
    }
    public  String date(Long time){
        Date date = new Date(1000*time);
        String format = dateFormat.format(date);
        return format;
    }
}
//size()结果小于5000,说明多线程出错了

参数传递

public class ThreadLocalTest1 {
    public static  ExecutorService executorService = Executors.newFixedThreadPool(10);
    static Set<String> set = new HashSet();
    public static void main(String[] args) throws InterruptedException {
        ThreadLocalTest1 threadLocalTest1 = new ThreadLocalTest1();
        for (int i = 0; i < 1000; i++) {
            int finalI = i;
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    String date =  threadLocalTest1.date(Long.parseLong(String.valueOf(finalI)));
                    System.out.println(date);
                    set.add(date);
                }
            });
        }
        Thread.sleep(5000);
        System.out.println(set.size());
    }
    public  String date(Long time){
        Date date = new Date(1000*time);
        SimpleDateFormat dateFormat = ThreadSafeFormatter.dateFormatThreadLocal.get();
        String format = dateFormat.format(date);
        return format;
    }
}

class ThreadSafeFormatter{
    public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal
            = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        }
    };
}
//为每个线程分配一个SimpleDateFormat,每个线程用自己的SimpleDateFormat处理(线程池有10个线程,为每个线程分配一个)

你可能感兴趣的:(java,SE,ThreadLocal)