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

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

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进行限制,第二种方法进行了限制,线程互斥运行必然会出现相互等待的情况,而第一种方法则没有限制。

线程系列4--Java线程范围内的共享数据(一)的更多相关文章

  1. 【java线程系列】java线程系列之java线程池详解

    一线程池的概念及为何需要线程池: 我们知道当我们自己创建一个线程时如果该线程执行完任务后就进入死亡状态,这样如果我们需要在次使用一个线程时得重新创建一个线程,但是线程的创建是要付出一定的代价的,如果在 ...

  2. 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型

    关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...

  3. Java并发编程系列-(6) Java线程池

    6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...

  4. Java并发编程系列-(7) Java线程安全

    7. 线程安全 7.1 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...

  5. 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁

    当涉及到多线程共享数据,需要数据同步的时候,就可以考虑使用线程锁了.本篇体验线程锁的各种用法以及线程死锁.主要包括: ※ 使用lock处理数据同步※ 使用Monitor.Enter和Monitor.E ...

  6. 【阿里面试系列】Java线程的应用及挑战

    文章简介 上一篇文章[「阿里面试系列」搞懂并发编程,轻松应对80%的面试场景]我们了解了进程和线程的发展历史.线程的生命周期.线程的优势和使用场景,这一篇,我们从Java层面更进一步了解线程的使用.关 ...

  7. 并发编程系列:Java线程池的使用方式,核心运行原理、以及注意事项

    并发编程系列: 高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 线程池的缘由 java中为了提高并发度,可以使用多线程共同执行,但是如果有大量线程短时间之内被创建和销毁,会占用大量的 ...

  8. java线程系列之三(线程协作)

    本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7433673,转载请注明. 上一篇讲述了线程的互斥(同步),但是在很多情况 ...

  9. java多线程与线程并发四:线程范围内的共享数据

    当多个线程操作同一个共有数据时,一个线程对共有数据的改变会影响到另一个线程.比如下面这个例子:两个线程调用同一个对象的的方法,一个线程的执行结果会影响另一个线程. package com.sky.th ...

随机推荐

  1. python之uWSGI和WSGI

    WSGI协议 首先弄清下面几个概念:WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web ...

  2. require.context() 用于获取一个特定上下文的,webpack的一个api

    参考链接: 1.https://www.jianshu.com/p/c894ea00dfec 2.https://www.jianshu.com/p/c894ea00dfec require.cont ...

  3. shell脚本基础和grep文本处理工具企业应用3

    文本处理工具:    linux上文本处理三剑客        grep,egrep,fgrep:文本过滤工具(模式:pattern)工具            grep:默认支持的是基本正则表达式: ...

  4. Linux用户组管理及用户权限3

    用户.组管理命令 安全上下文:        进程以其发起者的身份运行:            进程对文件的访问权限,取决于发此进程的用户的权限 系统用户:为了能够让那些后台进程或服务类进程以非管理员 ...

  5. C - Covered Points Count CodeForces - 1000C (差分,离散化,统计)

    C - Covered Points Count CodeForces - 1000C You are given nn segments on a coordinate line; each end ...

  6. java中activiti框架中的排他网关使用方法,多条件判断

    当排他网关的判断条件中出现多个条件时,需要注意,设置判断条件时,可能遇到,流向相同的任务,而判断条件的变量个数不同 那么,必须在后面的运行任务时,将所有的涉及到的变量都设置进任务中,只不过,如果这个任 ...

  7. BZOJ 1001 平面图转对偶图

    原图的面转成点,原图的边依旧边,只是连接的是两个面. 对偶图的点数=原图的面数 对偶图的边数=原图的边数(如果原边只属于一个面,则它为环边) #include<bits/stdc++.h> ...

  8. 生成静态libevent

    INCLUDE C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include D:\vs2013\VC\include LIB C:\Prog ...

  9. HelloWorld编写过程中注意事项

    一.package关键字 * package表示当前代码所属的包(package),是一种组织结构.其他package通过包名调用这个包下内容* package是必须的,每个文件的package必须存 ...

  10. 第二章 Vue快速入门--14 使用v-model实现计算器的案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...