ThrealLocal使用场景

  • 每个线程需要独享的对象,且这个对象是线程不安全的,所以需要ThreadLocal给每个线程复制一份 eg:Random、SimpleDateFormat 都是线程不安全的;

以下代码是通过线程池来打印各个线程的时间

`

 public static ExecutorService executorService = Executors.newFixedThreadPool(10);
 public static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

 public static void main(String[] args) {
     for (int i = 0; i < 10; i++) {
         int finalI = i;
         executorService.submit(new Runnable() {
             @Override
             public void run() {
                 Date date = TenThreadTest.date(finalI);
                 System.out.println(simpleDateFormat.format(date));
             }
         });
     }
     executorService.shutdown();
 }

 public static   Date date (int seconds) {
     return new Date(1000 * seconds);
 }

`

以上代码执行结果

`

  1970-01-01 08:00:02
  1970-01-01 08:00:06
  1970-01-01 08:00:05
  1970-01-01 08:00:02
  1970-01-01 08:00:02
  1970-01-01 08:00:08
  1970-01-01 08:00:02
  1970-01-01 08:00:02
  1970-01-01 08:00:09
  1970-01-01 08:00:07

`

大家有没有发现一个问题就是执行结果中存在重复的时间,根本原因就是 SimpleDateFormat 是线程不安全的,所有的线程共SimpleDateFormat,我们可以通过synchronized加锁,但是synchronized是阻塞的,如果线程的任务量特别大,效率会特别低;

以下是通过ThreadLocal加持过得实现方式:
十个线程都会有自己的 SimpleDateFormat 都是线程独享的

`

   public static ExecutorService executorService = Executors.newFixedThreadPool(10);

   public static void main(String[] args) {
       for (int i = 0; i < 1000; i++) {
           int finalI = i;
           executorService.submit(new Runnable() {
               @Override
               public void run() {
                   SimpleDateFormat simpleDateFormat = ThreadLocalFormat.simpleDateFormatThreadLocal.get();
                   Date date = TenThreadTest.date(finalI);
                   System.out.println(simpleDateFormat.format(date));
               }
           });
       }
       executorService.shutdown();
   }

   public static   Date date (int seconds) {
       return new Date(1000 * seconds);
   }

   static class ThreadLocalFormat {
       public static  ThreadLocal<SimpleDateFormat> simpleDateFormatThreadLocal = ThreadLocal.withInitial(() ->
               new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
   }

`

  • 每个线程内需要全局变量,不需要传参,可以让不同的方法直接使用

以下代码让当前用户在当前线程畅通无阻,不需要层层传递参数

`

package thread;

public class UsePart2 {

 public static void main(String[] args) {
     User user = new User();
     user.setName("王哈哈");
     UserContentHolder.threadLocal.set(user);

     new Service1().process();
     new Service2().process();
     new Service3().process();
 }

}

 class Service1 {
     public void process() {
         System.out.println("service1" + UserContentHolder.threadLocal.get().getName());
     }
 }
 
 
 class Service2 {
     public void process() {
         System.out.println("service2" + UserContentHolder.threadLocal.get().getName());
     }
 }


 class Service3 {
     public void process() {
         System.out.println("service3" + UserContentHolder.threadLocal.get().getName());
     }
 }
 
 class UserContentHolder{
     public static ThreadLocal<User> threadLocal = new ThreadLocal<User>();
}

 class User {
     public String getName() {
         return name;
     }

     public void setName(String name) {
         this.name = name;
     }
 
     private String name;
 }

`

运行结果:

`

service1王哈哈
service2王哈哈
service3王哈哈

`

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值