zoukankan      html  css  js  c++  java
  • Java ThreadLocal

    Java的ThreadLocal变量用来创建线程本地变量。我们知道,一个对象上的所有线程,都会共享该对象的变量,所以这些共享的变量不是线程安全的。我们可以使用synchronization同步语法来使得线程安全,但如果想避免使用synchronization,那么可以使用线程本地变量(ThreadLocal variables)。

    使用了ThreadLocal变量后,每个线程都有它自己的本地变量,可以通过get()、set()方法来获得或设置这些变量的值。ThreadLocal实例通常是类中想要将状态与线程关联的私有静态字段。

    下面通过一段代码来认识ThreadLocal:

    package com.journaldev.threads;
    
    import java.text.SimpleDateFormat;
    import java.util.Random;
    
    public class ThreadLocalExample implements Runnable{
    
        // SimpleDateFormat is not thread-safe, so give one to each thread
        private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
            @Override
            protected SimpleDateFormat initialValue()
            {
                return new SimpleDateFormat("yyyyMMdd HHmm");
            }
        };
        
        public static void main(String[] args) throws InterruptedException {
            ThreadLocalExample obj = new ThreadLocalExample();
            for(int i=0 ; i<10; i++){
                Thread t = new Thread(obj, ""+i);
                Thread.sleep(new Random().nextInt(1000));
                t.start();
            }
        }
    
        @Override
        public void run() {
            System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
            try {
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //formatter pattern is changed here by thread, but it won't reflect to other threads
            formatter.set(new SimpleDateFormat());
            
            System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
        }
    
    }

     这段代码的输出为:

    Thread Name= 0 default Formatter = yyyyMMdd HHmm
    Thread Name= 1 default Formatter = yyyyMMdd HHmm
    Thread Name= 0 formatter = yy-M-d ah:mm
    Thread Name= 2 default Formatter = yyyyMMdd HHmm
    Thread Name= 1 formatter = yy-M-d ah:mm
    Thread Name= 3 default Formatter = yyyyMMdd HHmm
    Thread Name= 4 default Formatter = yyyyMMdd HHmm
    Thread Name= 5 default Formatter = yyyyMMdd HHmm
    Thread Name= 2 formatter = yy-M-d ah:mm
    Thread Name= 6 default Formatter = yyyyMMdd HHmm
    Thread Name= 3 formatter = yy-M-d ah:mm
    Thread Name= 7 default Formatter = yyyyMMdd HHmm
    Thread Name= 8 default Formatter = yyyyMMdd HHmm
    Thread Name= 5 formatter = yy-M-d ah:mm
    Thread Name= 4 formatter = yy-M-d ah:mm
    Thread Name= 8 formatter = yy-M-d ah:mm
    Thread Name= 6 formatter = yy-M-d ah:mm
    Thread Name= 9 default Formatter = yyyyMMdd HHmm
    Thread Name= 7 formatter = yy-M-d ah:mm
    Thread Name= 9 formatter = yy-M-d ah:mm

    从输出可以看到,Thread-0已经更改了formatter的值,但是Thread-2仍旧输出了初始的formatter值,也就是说,线程拥有了自己的formatter变量。

    ThreadLocal类在Java 8中扩展了一个新的方法withInitial(),它将函数式接口作为参数,所以我们可以使用lambda表达式来轻松创建ThreadLocal实例。 例如,上面的格式化程序ThreadLocal变量可以在一行中定义如下:

    private static final ThreadLocal<SimpleDateFormat> formatter = 
        ThreadLocal.<SimpleDateFormat>withInitial
        (() -> {return new SimpleDateFormat("yyyyMMdd HHmm");});

    (完)

  • 相关阅读:
    [转帖]Javascript字符验证代码
    HTML标签转换函数
    [转帖]javascript做浮点数运算精确问题
    页面间参数传递
    js与asp.net的对话
    作死作死,完美主义,又“重写”了
    学习的最大动力是想要更加减少重复性工作
    三种可执行脚本的入门总结1
    [Python学习]遇到阻碍:可以在win平台下使用的unix shell环境
    .bat批处理脚本让cmd命令行提示符cd到工作目录
  • 原文地址:https://www.cnblogs.com/QG-whz/p/8334815.html
Copyright © 2011-2022 走看看