`
xiaofan_0204
  • 浏览: 124966 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线程范围内的共享变量(一)

    博客分类:
  • Java
 
阅读更多
关于线程范围内的变量共享,这种应用场景,在实际开发中应用不是很多,但对理解和加深多线程编程却有很大的好处!这里在网上找了一些资料,收藏仅供以后学习:
创建两个个线程,他们都访问同一个变量,要求同一个线程设置的值只能被自身所获取!

package com.datashare;

import java.util.Random;

public class ThreadDataShare {
	public static int data = 0;
	
	public static void main(String[] args) throws Exception {
		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 void get() {
			System.out.println("A from " + Thread.currentThread().getName()
					+ " get data : " + data);
		}
	}

	static class B {
		public void get() {
			System.out.println("A from " + Thread.currentThread().getName()
					+ " get data : " + data);
		}
	}
}


运行结果如下:
Thread-0 has put data :1118128123
Thread-1 has put data :1118128167
A from Thread-1 get data : 1118128167
A from Thread-0 get data : 1118128167
B from Thread-1 get data : 1118128167
B from Thread-0 get data : 1118128167

从结果中可以看出Thread-0该线程设置的值并没有被与该线程相关的类读取到!这使什么原因呢,这是因为,线程Thread-0刚把data设置值之后,还没来得及输出该值就被下个线程给改变了!所以线程一读取不到它自己设置的值!有可能甚至会出现Thread-0 has put data 和 Thread-1 has put data输出值相等的情况。

那怎么解决这种情况呢,办法有很多种:
其一:
package com.datashare;

import java.util.Random;

public class ThreadDataShare {
	public static int data = 0;

	public static void main(String[] args) throws Exception {
		for (int i = 0; i < 2; i++) {
			[b]Thread.sleep(100);[/b]			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 void get() {
			System.out.println("A from " + Thread.currentThread().getName()
					+ " get data : " + data);
		}
	}

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


粗体代码就是延长下个线程的创建时间,但是这样并不能解决根本问题!

方法二:
package com.datashare;

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

public class ThreadDataShare {
	public static int data = 0;

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

				@Override
				public void run() {
					[b]int data = new Random().nextInt();[/b]					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 void get() {
			System.out.println("A from " + Thread.currentThread().getName()
					+ " get data : " + map.get(Thread.currentThread()));
		}
	}

	static class B {
		public void get() {
			System.out.println("B from " + Thread.currentThread().getName()
					+ " get data : " + map.get(Thread.currentThread()));
		}
	}
}

其上实例是线程范围内变量共享的真实写照,上代码逻辑并不能于理解,需要注意的是data不是定义成了类变量了嘛,干嘛还要在此用一个方法的成员变量来覆盖!首先还得回到第一个实例,因为如果定义成类变量会出现第一个线程刚设置值马上又被第二个线程覆盖这种情况,所以才在方法里定义成方法的局部变量,每条线程会为各自的run方法分配各自的存储空间用于存储各自方法内部的局部变量,当这个方法结束时,分配给这个方法的栈就会被释放,栈中变量也会消失!而且很大程度上节省了内存!
分享到:
评论
1 楼 bugwolf 2012-12-02  
请问在方法二中,使用的是在方法run中定义的int data,那么实际上这个变量已经就不是类A和类B的共享变量,而成了run方法的私有变量,怎么能体现“线程间共享变量”的这个说法呢?

相关推荐

    Java多线程编程之ThreadLocal线程范围内的共享变量

    主要介绍了Java多线程编程之ThreadLocal线程范围内的共享变量,本文讲解了ThreadLocal的作用和目的、ThreadLocal的应用场景、ThreadLocal的使用实例等,需要的朋友可以参考下

    Java多线程与并发库高级应用视频教程22集

    【】01传统线程技术回顾【】02传统定时器技术回顾【】03传统线程互斥技术【】04传统线程同步通信技术【】04传统线程同步通信技术_分割纪录【】05线程范围内共享变量的概念与作用【】06ThreadLocal类及应用技巧【】06...

    C#线程锁介绍源码

    实际上在web开发中大多数逻辑都是在单个线程中展开的,一个请求都会在一个单独的线程中处理,其中的大部分变量都是属于这个线程的,根本没有必要考虑锁 定,当然对于ASP.NET中的Application对象中的数据,我们就要...

    多线程编程指南PDF

    多线程基础介绍.........................................................................................................................................15 定义多线程术语...................................

    多线程编程指南(系统描述了线程标准 线程同步 多线程编程原则 等)

    1 多线程基础介绍15 定义多线程术语15 符合多线程标准16 多线程的益处17 提高应用程序的响应 17 有效使用多处理器17 改进程序结构17 占用较少的系统资源17 结合线程和RPC(远程过程调用)18 多线程概念18 并发性和...

    谈谈Java中的ThreadLocal

    通过ThreadLocal可以将对象的可见范围限制在同一个线程内。  跳出误区  需要重点强调的的是,不要拿ThreadLocal和synchronized做类比,因为这种比较压根是无意义的!sysnchronized是一种互斥同步机制,是为了...

    Java虚拟机.docx

    (3)局部变量是线程安全的,如果方法内部的局部变量,没有逃离方法的作用范围 (4)栈内存溢出:栈帧过多,栈帧过大 3.本地方法栈:当Java去调用一些本地的C/C++方法时使用的栈,native关键字修饰的方法是间接去调用...

    API之网络函数---整理网络函数及功能

    LockFile 锁定文件的某一部分,使其不与其他应用程序共享 LockFileEx 与LockFile相似,只是它提供了更多的功能 lopen 以二进制模式打开指定的文件 lread 将文件中的数据读入内存缓冲区 lwrite 将数据从内存缓冲...

    超级有影响力霸气的Java面试题大全文档

    例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望...

    jsp内置对象的用法

    10 void setAttribute(String name,Object obj,int scope) 在指定范围内设置属性及属性值 11 public Object getAttribute(String name) 取属性的值 12 Object getAttribute(String name,int scope) 在指定范围...

    Java开发技术大全(500个源代码).

    variableScopeExample.java 变量使用范围示例 第3章 示例描述:本章学习对象和类。 accessMember.java 访问成员变量示例 constructNoPara.java 无参数的构造方法 constructWithPara.java 带参数的构造方法 ...

    JAVA面试题最全集

    静态变量和静态方法的意义,如何引用一个类的静态变量或者静态方法? 50.JAVA语言如何进行异常处理,关键字:thorws,throw,try,catch,finally 51.Object类(或者其子类)的finalize()方法在什么情况下被调用? 52....

    java 面试题 总结

    例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望...

    Java并发编程实战

    本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...

    并行计算导论(原书第2版).[美]Ananth Grama(带详细书签).pdf

    原版自1993年出版第1版到2003年出版第2版以来,已在世界范围内被广泛地采用为高等院校本科生和研究生的教材或参考书。 第1章 并行计算介绍 1.1 推动并行化 1.1.1 计算能力因素——从晶体管到浮点运算速度 1.1.2 ...

    Delphi5开发人员指南

    9.11.1 一个可以被共享数据的DLL 256 9.11.2 访问DLL中的共享数据 259 9.12 引出DLL中的对象 261 9.13 总结 265 第10章 Delphi 5的打印 266 10.1 TPrinter对象 266 10.2 TPrinter.Canvas 267 10.3 简单打印 267 ...

    java-servlet-api.doc

    服务器会在Web服务器或Servlet规定的时间内维持一个Session对象。当Session终止时,服务器会释放Session对象以及所有绑定在Session上的对象。 绑定对象到Session中 如果有助于你处理应用的数据需求,你也许需要绑定...

    Java性能优化

    尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最大限度的重用对象,最好能用基本的数据类型或数组来替代...

    java面试800题

    2.RequiredNew:当处于事务范围内的客户端应用调用组件商务方法时,EJB容器启动一个新的事务过程,组件商务方法执行在新事务过程范围内; 3.Mandatory:如果调用EJB组件商务方法的客户端应用不处于事务范围内,则...

Global site tag (gtag.js) - Google Analytics