在上一篇《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();
}
}
}

执行结果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGF3YW5nYW5iYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

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

Android多线程研究(6)——多线程之间数据隔离的更多相关文章

  1. Android中实现跨app之间数据的暴露与接收

    例如一个小项目:实现单词本的添加单词等功能 功能:不同的方式实现跨app之间数据的暴露与接收 暴露端app:实现单词的添加(Word.Translate),增删改查: 接收端app:模糊查询,得到暴露 ...

  2. 【转】Android进阶2之Activity之间数据交流(onActivityResult的用法)----不错

    原文网址:http://blog.csdn.net/sjf0115/article/details/7387467 主要功能: 在一个主界面(主Activity)上能连接往许多不同子功能模块(子Act ...

  3. Android进阶2之Activity之间数据交流(onActivityResult的用法) (转载)

    转自:http://blog.csdn.net/sjf0115/article/details/7387467 主要功能: 在一个主界面(主Activity)上能连接往许多不同子功能模块(子Activ ...

  4. Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程

    Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程 一丶获取进程以及父进程的pid 含义:    进程在内存中开启多个,操作系统如何区分这些进程, ...

  5. 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

    1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...

  6. ThreadLocal 多线程并发,数据隔离

    ThreadLocal:  创建一个线程本地变量. 本质:在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本. 优点:既实现多线程并发,游兼顾数据的安全性. 区别:Synchro ...

  7. VC中利用多线程技术实现线程之间的通信

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

  8. Android:Activity+Fragment及它们之间的数据交换.

    Android:Activity+Fragment及它们之间的数据交换 关于Fragment与Fragment.Activity通信的四种方式 比较好一点的Activity+Fragment及它们之间 ...

  9. Android 在不同Actitity之间数据传递

    本文实现一个简易的人品计算器来实践在不同Actitity之间数据传递 intent的数据传递 从A界面打开B界面 把A界面的数据传递给B界面 1. intent.setData(uri) -- int ...

随机推荐

  1. 喜马拉雅FM

    import requestsimport jsonstart_url ='https://www.ximalaya.com/revision/play/album?albumId=3595841&a ...

  2. Android布局之RelativeLayout

    RelativeLayout用到的一些重要的属性: 第一类:属性值为true或falseandroid:layout_centerHrizontal 水平居中android:layout_center ...

  3. 【Uva 10817】Headmaster's Headache

    [Link]: [Description] 一个学校,有s门课程(1<=s <=8),里面本身已经有m个老师了,然后还想招聘n个老师: 给出这m个老师和n个来应聘的老师的信息; (c[i] ...

  4. Android Netroid解析之——断点续传下载及问题修正

    提到Netroid也许非常多人不知道这个框架,但我假设说Volley想必没有人不知道吧. Netroid是一个基于Volley实现的Android Http库.提供运行网络请求.缓存返回结果.批量图片 ...

  5. C/C++获取本地时间常见方法

    跨平台方法 方法一:手动暴力法 #include <iostream> using namespace std; #include <time.h> time_t t = ti ...

  6. android5.x加入sim1,sim2标识

    1,mobile_signal_group.xml  ..... <FrameLayout android:id="@+id/mobile_combo" android:la ...

  7. js---16继承

    123 instanceof Number;//false,要左边是对象右边是函数 typeof 123 ; //number new Number(123) instanceof Number; / ...

  8. #学习笔记#——JavaScript 数组部分编程(二)

    2.移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回 function removeWithoutCopy(arr, item) { if(!A ...

  9. Myeclipse学习总结(2)——MyEclipse快捷键大全

    1.ctrl+shift+R 打开资源 此组快捷键可以打开工程中任意一个文件,而本人只需按文件名或者mask名的字母顺序输入就会出现对应的文件或者在内容中某个关键字再按快捷键也可以的,例如:Custo ...

  10. AES与RAS结合加解密方案

    import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyFactor ...