Java中如何实现单个线程范围内的数据共享

单个线程范围内的数据共享,就是确保当前的线程在执行的过程中,各个模块所引用的数据是一份,且所引用的数据不会因为其他线程的操作而变化。

以下是一段没有达到线程内数据共享的代码(参考自传智播客视频)

public class ThreadScopeShareData
{
    //用于存放随机产生的数据
    static int data = 0; 
    public static void main(String[] args)
    {
        //线程1
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                data = new Random().nextInt(1000);
                System.out.println(Thread.currentThread().getName() 
                        + "has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
        
        //线程2
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                data = new Random().nextInt(1000);
                System.out.println(Thread.currentThread().getName() 
                        + "has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
    }
}

class A
{
    public void getData()
    {
        System.out.println("A :" + Thread.currentThread().getName()
                + ": get data value:" + ThreadScopeShareData.data);
    }
}

class B
{
    public void getData()
    {
        System.out.println("B :" + Thread.currentThread().getName()
                + ": get data value:" + ThreadScopeShareData.data);
    }
}


控制台输出:


根据控制台的结果,可以看出,由于定义了static的变量存储数据,那么当线程2更改了data数据后,线程1中 A模块和B模块取出的和当初线程1放入的不是一个值,如何解决这个问题呢?见如下代码:


一、使用全局的map变量实现

public class ThreadScopeShareData
{
    //用于存放随机产生的数据
    //static int data = 0; 
    /*
     * 使用map类型的变量取代int类型的变量
     */
    static Map<Thread, Integer> map = new HashMap<Thread, Integer>();
    public static void main(String[] args)
    {
        //线程1
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                //data = new Random().nextInt(1000);
                int data = new Random().nextInt(1000);
                //用当前线程作为key,将当前线程产生的随机数,存入map中
                map.put(Thread.currentThread(), data);
                System.out.println(Thread.currentThread().getName() 
                        + " has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
        
        //线程2
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                int data = new Random().nextInt(1000);
                //用当前线程作为key,将当前线程产生的随机数,存入map中
                map.put(Thread.currentThread(), data);
                System.out.println(Thread.currentThread().getName() 
                        + " has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
    }
}

class A
{
    public void getData()
    {
        //使用当前线程作为map的key去取出map中对应的value
        System.out.println("A :" + Thread.currentThread().getName()
                + ": get data value:" 
                + ThreadScopeShareData.map.get(Thread.currentThread()));
    }
}

class B
{
    public void getData()
    {
      //使用当前线程作为map的key去取出map中对应的value
        System.out.println("B :" + Thread.currentThread().getName()
                + ": get data value:"
                + ThreadScopeShareData.map.get(Thread.currentThread()));
    }
}

二、使用ThreadLocal类,实现单个线程范围内 单个变量的数据共享

public class ThreadScopeShareData
{
    /*
     * 使用ThreadLocal
     */
    static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
    public static void main(String[] args)
    {
        //线程1
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                int data = new Random().nextInt(1000);
                //将当前线程产生的随机数,存入threadLocal中
                threadLocal.set(data);
                System.out.println(Thread.currentThread().getName() 
                        + " has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
        
        //线程2
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                int data = new Random().nextInt(1000);
                //将当前线程产生的随机数,存入threadLocal中
                threadLocal.set(data);
                System.out.println(Thread.currentThread().getName() 
                        + " has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
    }
}

class A
{
    public void getData()
    {
        //从threadLocal中取出value
        System.out.println("A :" + Thread.currentThread().getName()
                + ": get data value:" 
                + ThreadScopeShareData.threadLocal.get());
    }
}

class B
{
    public void getData()
    {
        //从threadLocal中取出value
        System.out.println("B :" + Thread.currentThread().getName()
                + ": get data value:"
                + ThreadScopeShareData.threadLocal.get());
    }
}

三、使用ThreadLocal实现 单个线程内 多个变量的数据共享

实现多个数据的共享可以使用Map去存放数据,这里就不说了 就是把ThreadLocal中的Integer替换成Map即可,主要贴一下使用对象存储多个变量的代码实现

①创建一个用于存放共享数据的类

/**
 * 存放共享数据的对象
 * @author ***
 *
 */
class ShareDataObj
{
    /**
     * threadLocal
     */
    private static ThreadLocal<ShareDataObj> threadLocal = 
        new ThreadLocal<ShareDataObj>();
    
    private ShareDataObj()
    {
    }
    
    /**
     * 返回从ThreadLocal中取出当前线程的ShareDataObj对象
     * @return
     */
    public static ShareDataObj getInstance4currentThread()
    {
        //从threadLocal变量中取出当前线程的ShareDataObj对象
        ShareDataObj dataObj = threadLocal.get();
        if(dataObj == null)
        {
            //1、创建一个新的对象
            dataObj = new ShareDataObj();
            //2、将创建的对象放入ShareDataObj对象中
            threadLocal.set(dataObj);
        }
        
        return dataObj;
    }
    
    //data1
    private int data1;
    //data2
    private String data2;

    public int getData1()
    {
        return data1;
    }

    public void setData1(int data1)
    {
        this.data1 = data1;
    }

    public String getData2()
    {
        return data2;
    }

    public void setData2(String data2)
    {
        this.data2 = data2;
    }
}

②操作共享数据

public class ThreadScopeShareData
{
    public static void main(String[] args)
    {
        //线程1
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                int data = new Random().nextInt(1000);
                //将当前线程产生的随机数,放入数据共享对象中
                ShareDataObj.getInstance4currentThread().setData1(data);
                ShareDataObj.getInstance4currentThread().setData2("str-" + data);
                
                System.out.println(Thread.currentThread().getName() 
                        + " has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
        
        //线程2
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                int data = new Random().nextInt(1000);
                //将当前线程产生的随机数,放入数据共享对象中
                ShareDataObj.getInstance4currentThread().setData1(data);
                ShareDataObj.getInstance4currentThread().setData2("str-" + data);
                
                System.out.println(Thread.currentThread().getName() 
                        + " has put data:" + data);
                //使用A对象输出数据
                new A().getData();
                //使用B对象输出数据
                new B().getData();
            }
        }).start();
    }
}

class A
{
    public void getData()
    {
        //从ShareDataObj中取出当前线程的数据共享对象
        System.out.println("A :" + Thread.currentThread().getName()
                + ": get data1:" 
                + ShareDataObj.getInstance4currentThread().getData1()
                + ", get data2:"
                + ShareDataObj.getInstance4currentThread().getData2());
    }
}

class B
{
    public void getData()
    {
        //从ShareDataObj中取出当前线程的数据共享对象
        System.out.println("B :" + Thread.currentThread().getName()
                + ": get data1:" 
                + ShareDataObj.getInstance4currentThread().getData1()
                + ", get data2:"
                + ShareDataObj.getInstance4currentThread().getData2());
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值