线程范围内共享数据(1)--》自己创建Map进行数据与当前线程的绑定

考虑一个场景:A转账给B ,我们会有账户A和账户B 两个对象,调用账户A的转出方法,调用B的转入方法,但是这两个方法要在同一事务中完成,如果有错误则回调,这两个对象方法使用同一个数据库连接,其它事务也会共享这个数据库连接,但是它们在各自的事务中有自己的数据库连接数据,互不影响。这就相当于同一个线程中调用两个模块的方法,它们的数据应该是一致的,而且与其它线程互不影响。

即我们的目的是;多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象

package com.effort.thread;

import java.util.Random;

public class ThreadShareData {

    private static  int data = 0 ;
    
    public static void main(String[] args) {
      for(int i = 0 ;i<2 ;i++){
        new Thread(new Runnable(){

            @Override
            public void run() {
                data = new Random().nextInt();
                System.out.println(Thread.currentThread().getName()+ " put random data:"+data);
                new A().get() ;
                new B().get() ;
            }
            
        }).start() ;
      }
        
    }
    
    static class A {
        public int get(){
            System.out.println("A from " + Thread.currentThread().getName() 
                    + " get data :" + data);
            return data ;
        }
    }
    
    static class B{
        public int get(){
            System.out.println("B from " + Thread.currentThread().getName() 
                    + " get data :" + data);
            return data ;
        }
    }
}

模块A ,B都需要访问static的变量data   在线程0中会随机生成一个data值 假设为10  那么此时模块A和模块B在线程0中得到的data的值为10 ;在线程1中 假设会为data赋值为20 那么在当前线程下

模块A和模块B得到data的值应该为20 

       看程序执行的结果:

Thread-0 put random data:-1344602819
Thread-1 put random data:-1842611697
A from Thread-1 get data :-1842611697
A from Thread-0 get data :-1842611697
B from Thread-1 get data :-1842611697
B from Thread-0 get data :-1842611697

在线程0中执行模块A和模块B的方法去获取data的值 但是在获取之前  线程1就将data的值给修改为-1842611697 导致线程0中的模块A和模块B获取了错误的数据.  

那么如何得到正确的效果呢? 

可以将data数据和当前允许的线程绑定在一块,在模块A和模块B去获取数据data的时候 是通过当前所属的线程去取得data的结果就行了。

 声明一个Map集合 集合的Key为Thread 存储当前所属线程 Value 保存data的值,代码如下: 

package com.effort.thread;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadShareData {

    private static  int data = 0 ;
    private static Map<Thread,Integer> threadData = new HashMap<Thread, Integer>() ;
    
    public static void main(String[] args) {
      for(int i = 0 ;i<2 ;i++){
        new Thread(new Runnable(){

            @Override
            public  void run() {
                synchronized (ThreadShareData.class) {  //保证下面的代码都执行完才允许其他线程进入
                    data = new Random().nextInt();
                    threadData.put(Thread.currentThread(), data) ; //将数据绑定到带当前线程
                    System.out.println(Thread.currentThread().getName()+ " put random data:"+data);
                    new A().get() ;
                    new B().get() ;
                }
            }
            
        }).start() ;
      }
        
    }
    
    static class A {
        public int get(){
            //取数据都从当前线程中取得 
            int d = threadData.get(Thread.currentThread()) ;
            System.out.println("A from " + Thread.currentThread().getName() 
                    + " get data :" + d);
            return data ;
        }
    }
    
    static class B{
        public int get(){
            //取数据都从当前线程中取得 
            int d  = threadData.get(Thread.currentThread()) ;
            System.out.println("B from " + Thread.currentThread().getName() 
                    + " get data :" + d);
            return data ;
        }
    }
}
程序执行结果:

Thread-0 put random data:-1842492021
A from Thread-0 get data :-1842492021
B from Thread-0 get data :-1842492021
Thread-1 put random data:-1886142929
A from Thread-1 get data :-1886142929
B from Thread-1 get data :-1886142929

达到效果。

下一节学习ThreadLocal的基本使用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值