• Android多线程研究(6)——多线程之间数据隔离


    在上一篇《Android多线程研究(5)——线程之间共享数据》中对线程之间的数据共享进行了学习和研究,这一篇我们来看看怎样解决多个线程之间的数据隔离问题,什么是数据隔离呢?比方说我们如今开启了两个线程,这两个线程都要同一时候给同一个全局变量data赋值。各个线程操作它赋值后的变量数据,这里就须要用到隔离。先看一段代码:

    import java.util.Random;
    
    
    public class ThreadLocalTest {
    	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() +
    							" has put data: " + data);
    					new A().get();
    					new B().get();
    				}
    			}).start();
    		}
    	}
    	
    	static class A{
    		public int get(){
    			System.out.println("A from " + Thread.currentThread().getName() +
    					" has get data: " + data);
    			return data;
    		}
    	}
    	
    	static class B{
    		public int get(){
    			System.out.println("B from " + Thread.currentThread().getName() +
    					" has get data: " + data);
    			return data;
    		}
    	}
    }
    
    执行结果:

    从上面我们能够看到Thread-0和Thread-1都在操作变量data,可是两个线程之间没有做到对数据操作的隔离,所以输出结果中两个线程共用了一个data变量。

    我们将上面代码改动例如以下:

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    
    
    public class ThreadLocalTest {
    	//private static int data = 0;
    	private static Map<Thread, Integer> map = 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() {
    					//data = new Random().nextInt();
    					int data = new Random().nextInt();
    					map.put(Thread.currentThread(), data);
    					System.out.println(Thread.currentThread().getName() +
    							" has put data: " + data);
    					new A().get();
    					new B().get();
    				}
    			}).start();
    		}
    	}
    	
    	static class A{
    		public int get(){
    			System.out.println("A from " + Thread.currentThread().getName() +
    					" has get data: " + map.get(Thread.currentThread()));
    			return map.get(Thread.currentThread());
    		}
    	}
    	
    	static class B{
    		public int get(){
    			System.out.println("B from " + Thread.currentThread().getName() +
    					" has get data: " + map.get(Thread.currentThread()));
    			return  map.get(Thread.currentThread());
    		}
    	}
    }
    
    输出结果:

    上面代码中我们用一个Map集合隔离了线程对data数据的操作。事实上相当于创建了一个data数据的备份(双份的data)实现了线程之间数据的隔离。事实上早在Java 1.2就引入了一个用来支持线程数据隔离的类(java.lang.ThreadLocal),以下我们来看看怎样使用ThreadLocal实现线程之间的数据隔离。

    ThreadLocal中的三个方法:‘

    get() :返回当前线程的线程局部变量副本

    protected initialValue() :返回该线程局部变量的当前线程的初始值

    void set(Object value) :设置当前线程的线程局部变量副本的值

    当中initialValue方法是为子类写的方法,在一个线程第一次调用get()或者set()方法时执行,而且仅执行一次。

    import java.util.Random;
    
    
    public class ThreadLocalTest {
    	//private static int data = 0;
    	//private static Map<Thread, Integer> map = new HashMap<Thread, Integer>();
    	private static ThreadLocal<Integer> tl = new ThreadLocal<Integer>();
    	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();
    					int data = new Random().nextInt();
    					//map.put(Thread.currentThread(), data);
    					tl.set(data);
    					System.out.println(Thread.currentThread().getName() +
    							" has put data: " + data);
    					new A().get();
    					new B().get();
    				}
    			}).start();
    		}
    	}
    	
    	static class A{
    		public int get(){
    			System.out.println("A from " + Thread.currentThread().getName() +
    					" has get data: " + tl.get());
    			return tl.get();
    		}
    	}
    	
    	static class B{
    		public int get(){
    			System.out.println("B from " + Thread.currentThread().getName() +
    					" has get data: " + tl.get());
    			return  tl.get();
    		}
    	}
    }
    
    执行结果:

    上面代码明显少了非常多。事实上ThreadLocal中底层也是用Map来存储变量副本实现的。






  • 相关阅读:
    FFT 和 NTT
    神秘构造题
    P4396 [AHOI2013]作业
    杜教筛学习笔记
    杜教筛
    「$mathcal{Darkbzoj}$」神犇和蒟蒻
    「CQOI2015」选数
    「$mathcal{Atcoder}$」$mathcal{ARC101}$
    「NOI2019」退役记???
    「李超线段树」
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6984373.html
Copyright © 2020-2023  润新知