这张图片是我看传智播客的视频时的截屏,这个图片很直观的展示了线程范围内的数据共享。当同一个线程在执行三个不同业务模块时,这三个业务模块访问的数据是共享的。更直白的说,当一个执行线索在穿个每个业务模块时,这个执行线索在执行业务模块时,所调用的数据资源是共享的。线程范围内,是指同一个的执行线索的范围内。不同的线程是指不同的执行线索,不同的线程当然也就不属于同一个线程范围。

下面我们进入正题,依然是使用传智播客中的讲解内容作为今天的分析用例,挽起袖子开始撸代码。

public class ThreadScopeData {
	
	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() {
					int data = new Random().nextInt();
					System.out.println("线程名字:"+Thread.currentThread().getName()+",设置的data数据为:"+data);
					threadData.put(Thread.currentThread(), data);
					new Songzl().getData();
					new Wangxl().getData();
				}
			}).start();
		}
	}
	
	static class Songzl{
		private void getData(){
			int data = threadData.get(Thread.currentThread());
			System.out.println("线程名字:"+Thread.currentThread().getName()+"业务方法songzl获取的data数据为:"+data);
		}
	}
	
	static class Wangxl{
		private void getData(){
			int data = threadData.get(Thread.currentThread());
			System.out.println("线程名字:"+Thread.currentThread().getName()+"业务方法wangxl获取的data数据为:"+data);
		}
	}
}

上面这个是张孝祥老师给出的实例代码,解决同一个线程范围内的数据共享问题。线程范围内的数据共享,可以理解为将数据单独复制出来一份,并且将数据和线程绑定起来。数据和线程被绑定在一起,被执行的模块都通过线程去寻找对应绑定的数据,那么取出来的数据必然是一直的。

下面这个方法是我个人写出来的,同样能实现线程内的数据共享:

public class ThreadScopeDataDemo {

	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() {
                        //使用类的字节码对象,作为同步锁 synchronized (ThreadScopeDataDemo.class) { data = new Random().nextInt(); System.out.println("线程名字:"+Thread.currentThread().getName()+",设置的data数据为:"+data); new Songzl().getData(); new Wangxl().getData(); } } }).start(); } } static class Songzl{ private void getData(){ System.out.println("线程名字:"+Thread.currentThread().getName()+"业务方法songzl获取的data数据为:"+data); } } static class Wangxl{ private void getData(){ System.out.println("线程名字:"+Thread.currentThread().getName()+"业务方法wangxl获取的data数据为:"+data); } } }

上面的代码同样可以实现线程范围内的数据共享,区别是没有使用map存放线程对象,而是使用同步锁的方式来实现。通过上面的代码我们可以更好的理解,为什么多线程的时候数据会取错,原因就是当cup执行的时候,在多个线程间切换运行,导致一个线程的业务没有执行完毕,就跳到了另个线程执行。我们将数据和线程绑定,就是为了避免较差执行,出现数据错乱的问题。我们加同步锁,同样也是保证,一个线程正常执行完毕后,再让另一个线程执行,这样也能保证同一个线程的执行范围内数据共享。但是从代码的角度分析,上面的俩种实现方法,第一种的性能应该高于第二种。因为第一种没有对cup进行限制,第二种方法进行了限制,线程互斥运行必然会出现相互等待的情况,而第一种方法则没有限制。

 

posted on 2017-10-22 21:25  傲视苍穹  阅读(179)  评论(0编辑  收藏  举报