zoukankan      html  css  js  c++  java
  • 八、ThreadLocal

    先看示例:

    public class ThreadTest{
    
        private static int num1 = 0;
        @Test
        public void m1(){
            for(int i = 0 ;i<2;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        num1= new Random().nextInt();
                        System.out.println(Thread.currentThread().getName()+": data : "+num1);
                        new A();
                    }
                }).start();
            }
        }
        
        class A{
            public A() {
                System.out.println("A :"+Thread.currentThread().getName()+" data : "+num1);
            }
        }
        
    
    }

    上面示例中,定义了一个类变量num1,创建两个线程分别给num1赋随机值然后打印,在内部类A中也对num1的值进行打印。整个过程中,变量num1为所有线程所共享,只要有一个线程将其值改变,其它线程的值也会跟着改变。那么问题就来了,在很多时候,我们在一个线程中处理的数据,仅希望它在当前线程中有效,而不受其它线程的影响。也就是说,数据仅在当前线程中传播。那么,该如何实现呢?

    public class ThreadTest {
        /**
         * 当以一个map,用来存储当前线程的数据
         */
        private static Map<Thread,Integer> map = new HashMap<Thread,Integer>();
        @Test
        public void m2(){
            for(int i = 0 ;i<2;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        int num2 = new Random().nextInt();
                        map.put(Thread.currentThread(), num2);  //将值绑定到当前线程中。
                        System.out.println(Thread.currentThread().getName()+": data : "+num2);
                        new B();
                    }
                }).start();
            }
        }
        class B{
            public B() {
                int num2 = map.get(Thread.currentThread());  //取出当前线程的共享变量
                System.out.println("B :"+Thread.currentThread().getName()+" data : "+num2);
            }
        }
    
    }

    上面的示例中,已经实现了在线程的范围内共享。但是,灵活性不足。在lang包下已经为我们实现了线程局部变量的类ThreadLocal。

    public class ThreadLocal {
        /**
         * 创建一个线程局部变量
         */
        private static ThreadLocal<Integer> local = new ThreadLocal<Integer>();
        @Test
        public void m3(){
            for(int i = 0 ;i<2;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        int num3 = new Random().nextInt();
                        local.set(num3);  //线程局部变量赋值。
                        System.out.println(Thread.currentThread().getName()+": data : "+num3);
                        new C();
                    }
                }).start();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        class C{
            public C() {
                int num3 = local.get();  //取出当前线程的局部变量
                System.out.println("C :"+Thread.currentThread().getName()+" data : "+num3);
            }
        }
    
    }

    版本四:这样写的好处自己体会。

    public class ThreadLocalTest2 {
            @Test
        public void m4(){
            for(int i = 0 ;i<5;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        int num4 = new Random().nextInt();
                        System.out.println(Thread.currentThread().getName()+": data : "+num4);
                        D d = D.getD();
                        d.setData(num4);
                        d.printD();
                    }
                }).start();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 将线程局部变量封装到一个类里面
     */
    class D{
        private static ThreadLocal<D> current= new ThreadLocal<D>();
        
        private int data;
        
        private D(){}
        
        public static D getD(){
            if(current.get() == null){
                current.set(new D());
            }
            return current.get();
        }
        
        public int getData() {
            return data;
        }
        public void setData(int data) {
            this.data = data;
        }
        
        public void printD(){
            System.out.println(Thread.currentThread()+": D : data:"+data);
        }
    }
  • 相关阅读:
    常用的XML读写
    未能使用提供程序 "RsaProtectedConfigurationProvider" 进行解密 的解决办法
    (原创)Urlrewrite 独立配置文件的使用方法
    The Two Interceptors: HttpModule and HttpHandlers
    根据最后修改时间查询存储过程
    Net下WinForm皮肤插件资源
    C# 主线程 辅助线程
    浅述WinForm多线程编程与Control.Invoke的应用
    ASP.NET实现图片防盗链
    URLRewrite 实现方法详解
  • 原文地址:https://www.cnblogs.com/futiansu/p/5616001.html
Copyright © 2011-2022 走看看