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

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

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. ES6基础之——new Set

    Set 对象存储的值总是唯一的 Set 对象方法 方法 描述 add 添加某个值,返回Set对象本身. clear 删除所有的键/值对,没有返回值. delete 删除某个键,返回true.如果删除失 ...

  2. vue进阶:vs code添加vue代码片段

    如何设置? 选择或创建 配置代码 如何使用? 一.如何设置? 进入vs code主界面-->使用快捷键“ctrl + shift + p”: 如果你是使用Preferences:Configur ...

  3. 1.Linux文件及目录结构

    Linux 文件结构 在Linux中 ,一切皆文件 目录结构

  4. fastadmin中关联表时A为主表,想让B表和C表关联时怎么办?

    $sql = Db::connect('数据库')->table('C表')->where('status', 'normal')->field('字段 别称[不可与其他表重复]') ...

  5. odoo 关系字段(关联关系)

    Many-to-one关联 publisher_id = fields.Many2one(comodel_name= 'res.partner', domain='',context={},ondel ...

  6. Go语言基础之操作Redis

    Go语言操作Redis 在项目开发中redis的使用也比较频繁,本文介绍了Go语言如何操作Redis. Redis介绍 Redis是一个开源的内存数据库,Redis提供了5种不同类型的数据结构,很多业 ...

  7. 电子工程师需要了解的SMT贴片质量问题汇总(转)

    点胶工艺中常见的缺陷与解决方法 拉丝/拖尾 拉丝/拖尾是点胶中常见的缺陷,产生的原因常见有胶嘴内径太小.点胶压力太高.胶嘴离PCB的间距太大.贴片胶过期或品质不好.贴片胶粘度太好.从冰箱中取出后未能恢 ...

  8. Thymeleaf初探

    Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎.类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用 ...

  9. 执行nvidia-smi出错

    执行nvidia-smi出错 NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make su ...

  10. javac & java

    # 没有 package, 没有 import 的情况 * 源文件 public class HelloWorld{ public static void main(String[] args){ S ...