在上一篇《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. 为什么linux驱动中变量或者函数都用static修饰?(知乎问题)

    static定义的全局变量 或函数也只能作用于当前的文件. 世界硬件厂商太多,定义static为了防止变量或 函数 重名,定义成static, 就算不同硬件驱动中的 变更 或函数重名了也没关系 .

  2. Centos6.5 安装lamp环境

    转载自:http://www.jb51.net/article/37987.htm (转载请注明出处,谢谢) 准备篇: 1.配置防火墙,开启80端口.3306端口vi /etc/sysconfig/i ...

  3. php https链接

    1.安装soap扩展 2.安装openssL 3.代码执行 function  issure($sn){//通过soap链接接口  进行确认是否是正确的sn码    try{        $clie ...

  4. iOS基本UI控件总结

    包括以下几类: //继承自NSObject:(暂列为控件) UIColor *_color;    //颜色 UIImage *_image;    //图像 //继承自UIView:只能相应手势UI ...

  5. [Python] String Join

    Let's introduce a new string method, join: >>> nautical_directions = "\n".join([& ...

  6. Silverlight 应用程序中未处理的错误

    Silverlight 开发中遇到个错误: SCRIPT5022: Silverlight 应用程序中未处理的错误 代码: 2108 类别: InitializeError 消息: 无法下载初始屏幕或 ...

  7. Spring MVC : Java模板引擎 Thymeleaf (三)

    以下以构造一个表单開始,解说 Thymeleaf的使用方法. 为了演示方便,还是以经典的注冊为例. 这是Thymeleaf的form的形式, <form action="#" ...

  8. Oracle的表空间和sqlplus

    1.  表空间的概念 曾经接触过的数据库都没有听到过表空间这个词,在前一段时间看到Oracle数据库的时候发现表空间无处不在. 所以表空间在Oracle数据库中应该是一个非经常常使用而且非常重要的概念 ...

  9. 转:向IOS设备发送推送通知

    背景 SMS 和 MMS 消息是由无线运营商通过设备的电话号码向特定设备提供的.实现 SMS/MMS 的服务器端应用程序的开发人员必须费大量精力才能与现有的封闭电信基础架构进行交互(其中包括获取电话号 ...

  10. Android引入library失败的可能原因

    eclipse环境,引入library一直失败 谷歌到的原因是 Windows下 目标工程必须和引用工程在同一磁盘盘符下 然后我将要引入的library项目移动和现在项目同一磁盘下,引入成功 至于为什 ...