java thread 共享数据_Java中的线程--线程范围内共享数据

接着学习Java中的线程,线程范围内的共享数据!

一、线程范围内的数据共享定义

对于相同的程序代码,多个模块在同一个线程中共享一份数据,而在另外线程中运行时又共享另外一份数据。

共享数据中存在的问题,代码如下:

1 //A 和 B共享数据data,但是在这种情况下 会存在问题

2 public classThreadScopeShareData {3

4 private static int data = 0;5

6 public static voidmain(String[] args) {7 for (int i = 0; i < 10; i++) {8 new Thread(newRunnable() {9 @Override10 public voidrun() {11 data = newRandom().nextInt();12 System.out.println(Thread.currentThread().getName() + "has put data " +data);13 newA().get();14 newB().get();15 }16 }).start();17 }18 }19

20 static classA {21 public voidget() {22 System.out.println("A from " + Thread.currentThread().getName() + "has put data " +data);23 }24 }25

26 static classB {27 public voidget() {28 System.out.println("B from " + Thread.currentThread().getName() + "has put data " +data);29 }30 }31

32 }

运行结果如下:(好像是有点乱七八糟的感觉)

1 Thread-3has put data 1233171571

2 Thread-7has put data -1796246182

3 Thread-1has put data -609826403

4 A from Thread-3has put data 1961867182

5 A from Thread-1has put data 1961867182

6 Thread-8has put data 2116621494

7 A from Thread-8has put data 1961867182

8 Thread-5has put data -609826403

9 A from Thread-5has put data 1961867182

10 A from Thread-7has put data 1961867182

11 B from Thread-7has put data 1961867182

12 B from Thread-5has put data 1961867182

13 Thread-6has put data -609826403

14 A from Thread-6has put data 1961867182

15 B from Thread-6has put data 1961867182

16 Thread-0has put data 1233171571

17 A from Thread-0has put data 1961867182

18 B from Thread-0has put data 1961867182

19 Thread-9has put data 1961867182

20 A from Thread-9has put data 1961867182

21 B from Thread-9has put data 1961867182

22 B from Thread-1has put data 1961867182

23 Thread-2has put data 1233171571

24 Thread-4has put data 1233171571

25 A from Thread-4has put data 1961867182

26 B from Thread-4has put data 1961867182

27 B from Thread-8has put data 1961867182

28 B from Thread-3has put data 1961867182

29 A from Thread-2has put data 1961867182

30 B from Thread-2has put data 1961867182

解决方案如下,用线程范围内的变量,当然这个是比较粗糙的解决方案,代码如下:

1 public classThreadScopeShareData {2

3 private static int data = 0;4 //这个用来存放当前线程内的共享数据

5 private static Map threadData = new HashMap();6

7 public static voidmain(String[] args) {8 for (int i = 0; i < 10; i++) {9 new Thread(newRunnable() {10 @Override11 public voidrun() {12 int data = newRandom().nextInt();13 System.out.println(Thread.currentThread().getName() + "has put data " +data);14 threadData.put(Thread.currentThread(), data);15 newA().get();16 newB().get();17 }18 }).start();19 }20 }21

22 static classA {23 public voidget() {24 int data =threadData.get(Thread.currentThread());25 System.out.println("A from " + Thread.currentThread().getName() + "has put data " +data);26 }27 }28

29 static classB {30 public voidget() {31 int data =threadData.get(Thread.currentThread());32 System.out.println("B from " + Thread.currentThread().getName() + "has put data " +data);33 }34 }35

36 }

二、JDK中解决线程共享数据(ThreadLocal)

优化解决方法,更加优雅的代码,更加人性化的解决方法,使得用户用起来更加方便,封装到ThreadLocal中,并且得保证同一个线程,所得到的的是同一份数据!

改造之后的实体对象,代码如下:

1 //改造之后的实体类,封装创建方法,并且封装ThreadLocal,来保证同一个线程得到的同一个对象

2 public classMyThreadScopeData {3

4 privateString name;5 private intage;6 //private static MyThreadScopeData instance = null;

7 private static ThreadLocal map = new ThreadLocal();8

9 privateMyThreadScopeData() {10

11 }12

13 public static /*synchronized*/MyThreadScopeData getThreadInstance() {14 MyThreadScopeData instance =map.get();15 if(instance == null) {16 instance = newMyThreadScopeData();17 map.set(instance);18 }19 returninstance;20 }21

22 publicString getName() {23 returnname;24 }25

26 public voidsetName(String name) {27 this.name =name;28 }29

30 public intgetAge() {31 returnage;32 }33

34 public void setAge(intage) {35 this.age =age;36 }37

38 }

测试类中代码如下:

1 public classThreadLocalTest {2

3 private static ThreadLocal x = new ThreadLocal();4 private static ThreadLocal myThreadLocal = new ThreadLocal();5

6 public static voidmain(String[] args) {7 //相当于创建了10个线程

8 for (int i = 0; i < 10; i++) {9 new Thread(newRunnable() {10 @Override11 public voidrun() {12 int data = newRandom().nextInt();13 System.out.println(Thread.currentThread().getName() + "has put data " +data);14 //MyThreadScopeData myData = new MyThreadScopeData();15 //myData.setName("name" + data);16 //myData.setAge(data);17 //myThreadLocal.set(myData);

18

19 MyThreadScopeData.getThreadInstance().setName("name" +data);20 MyThreadScopeData.getThreadInstance().setAge(data);21 //存放的是与当前线程相关的数据

22 x.set(data);23

24

25 newA().get();26 newB().get();27 }28 }).start();29 }30 }31

32 static classA {33 public voidget() {34 int data =x.get();35 System.out.println("A from " + Thread.currentThread().getName() + "has get data " +data);36

37 //MyThreadScopeData myData = myThreadLocal.get();38 //System.out.println("A from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","39 //+ myData.getAge());

40

41 MyThreadScopeData myData =MyThreadScopeData.getThreadInstance();42 System.out.println("A from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","

43 +myData.getAge());44 }45 }46

47 static classB {48 public voidget() {49 int data =x.get();50 System.out.println("B from " + Thread.currentThread().getName() + "has get data " +data);51

52 //MyThreadScopeData myData = myThreadLocal.get();53 //System.out.println("B from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","54 //+ myData.getAge());

55

56 MyThreadScopeData myData =MyThreadScopeData.getThreadInstance();57 System.out.println("B from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","

58 +myData.getAge());59 }60 }61 }

总结:这个线程范围内的数据共享问题,解决的方法中用到了单例模式中的设计思想,但是区别的地方是加了一步将数据存放到ThreadLocal 中,实现数据的共享!

三、多线程访问共享数据和线程的方式

也是线程间数据共享的问题,只不过这个是以实战的角度来探索线程共享间数据的同步问题,主要学的是这种解决实际问题的能力,看看代码:

1 public classMultiThreadShareData {2

3 public static voidmain(String[] args) {4 final ShareData1 data1 = newShareData1();5

6 new Thread(newRunnable() {7 @Override8 public voidrun() {9 data1.decrement();10 }11 }).start();12

13 new Thread(newRunnable() {14 @Override15 public voidrun() {16 data1.increment();17 }18 }).start();19 }20

21 static class ShareData1 /*implements Runnable*/{22

23 private int j = 0;24 private int count = 100;25

26 public synchronized voidincrement() {27 j++;28 }29

30 public synchronized voiddecrement() {31 j--;32 }33

34 /*

35 * @Override public void run() { while (true) { count--; } }36 */

37 }38

39 }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值