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);
        }
    }
  • 相关阅读:
    html5_css 3 学习指南__转
    MySQL常见故障处理手册_转
    MYSQL出错代码列表——转
    Redhat 6环境下安装Oracle 12c的方法
    Wireshark入门:分析DHCP协议的运行
    重命名Oracle数据库的表空间(Renaming a Tablespace)
    Oracle DB 分区特性概述 Overview of Partitions
    Oracle Database Concepts:介绍模式对象(Introduction to Schema Objects)
    Supporting Connected Routes to Subnet Zero
    Secondary IP Addressing
  • 原文地址:https://www.cnblogs.com/futiansu/p/5616001.html
Copyright © 2011-2022 走看看