Java多线程(四)——多线程数据隔离与共享
目录
一、引言
二、数据隔离
三、数据共享
1、传入Runnable赋值成员变量
2、新建外部类添加成员变量(这个是教程3中用到的,我比较常用)
四、总结
一、引言
多线程数据隔离与数据共享是个矛盾体,有些数据需要隔离,比如每个人的银行账户,有些需要共享比如买票的总火车票数量,这个问题导致了这篇文章的出现,抽象出了这两类问题。
二、数据隔离
多线程之间就是因为数据共享在多个线程才导致了线程不安全,这就要求线程间的数据需要隔离,从根本上解决了线程安全问题,比如我们每个人都有自己的银行账户,每次存钱行为一样,但是都存入了自己的银行账户而不是通用的银行账户。
这个问题ThreadLocal变量帮我们解决了这个问题,我们只需要创建该变量,在每个线程里面使用相当于它在每个线程里面都有一个相同名字的变量供我们使用。
public class TestThreadlocal {static ThreadLocal<Student> threadLocalst=new ThreadLocal<Student>();public static void main(String [] args){//System.out.print("asdf");for (int i=0;i<10;i++){new Thread(new Runnable() {public void run() {Student student=new Student();student.setAge(new Random().nextInt() +"");student.setName("xcy");System.out.println(Thread.currentThread().getName()+ student.getName()+student.getAge());threadLocalst.set(student);new A().get();new B().get();}}){}.start();}}static class A{public void get (){Student st=threadLocalst.get();System.out.println(Thread.currentThread().getName()+ st.getName()+st.getAge());}}static class B{public void get (){Student st=threadLocalst.get();System.out.println(Thread.currentThread().getName()+ st.getName()+st.getAge());}}}
student类
public class Student {private String name;private String age;private boolean flag;public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}}
运行结果:同一个线程添加的和取出的是同一个值
Thread-4xcy-1021967251
Thread-2xcy1234085798
Thread-1xcy207906111
Thread-3xcy1042697540
Thread-7xcy-420182191
Thread-0xcy127646899
Thread-6xcy-383177740
Thread-4xcy-1021967251
Thread-0xcy127646899
Thread-5xcy-80755785
Thread-5xcy-80755785
Thread-9xcy650715745
Thread-3xcy1042697540
Thread-8xcy1574576955
Thread-2xcy1234085798
Thread-1xcy207906111
Thread-9xcy650715745
Thread-9xcy650715745
Thread-5xcy-80755785
Thread-0xcy127646899
Thread-7xcy-420182191
Thread-6xcy-383177740
Thread-6xcy-383177740
Thread-7xcy-420182191
Thread-3xcy1042697540
Thread-4xcy-1021967251
Thread-2xcy1234085798
Thread-1xcy207906111
Thread-8xcy1574576955
Thread-8xcy1574576955
这个原理是什么呢?简单来讲就是创建了个HashMap,在每个线程中添加.put(当前thread名称,添加数据),然后取出的时候也是取出.get(当前thread名称),自然得到的是当前线程的数据。
上述例子升级版——单例模式
保证类有且只有一个实例,这里是保证每个线程有且只有一个student类,慢慢体会。struts中就是用的这个原理,每个线程的数据是隔离的
public class TestThreadlocal {public static void main(String [] args){for (int i=0;i<10;i++){new Thread(new Runnable() {public void run() {Student student=Student.getInstance();student.setAge(new Random().nextInt() +"");student.setName("xcy");System.out.println(Thread.currentThread().getName()+ student.getName()+student.getAge());new A().get();new B().get();}}){}.start();}}static class A{public void get (){Student st=Student.getInstance();System.out.println(Thread.currentThread().getName()+ st.getName()+st.getAge());}}static class B{public void get (){Student st=Student.getInstance();System.out.println(Thread.currentThread().getName()+ st.getName()+st.getAge());}}}
student单例类
public class Student {//Student(){}private static ThreadLocal<Student> map=new ThreadLocal<Student>();public static Student getInstance(){if (map.get()==null){map.set(new Student());}return map.get();}//private String name;private String age;private boolean flag;public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}}
三、数据共享
多线程之间就是因为数据共享在多个线程才导致了线程不安全,有些数据需要隔离,而有些必须要共享,比如火车票总数对买个买票的人共享。
这里主要有两种方式
1、传入Runnable赋值成员变量
共享数据封装成另外一个对象中封装成另外一个对象中,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对数据进行各个操作的互斥和通信
2、新建外部类添加成员变量(这个是教程3中用到的,我比较常用)
与第一种方法的区别在于第二种方法巧妙的用了内部类共享外部类数据的思想,即把要共享的数据变得全局变量,这样就保证了操作的是同一份数据。同时内部类的方式使代码更加简洁。但是不如第一种解法条理那么清楚
四、总结
- 数据隔离threadlocal;
- 数据隔离单例模式;
- 数据共享data传入;
- 数据共享data存在外部类;
Java多线程(四)——多线程数据隔离与共享相关推荐
- 并发编程02-什么是线程安全以及Java虚拟机中哪些数据是线程共享的,那些是线程私有的
线程安全的本质 什么是线程安全 要说什么是线程安全,那么我们看看生活中例子吧. 场景1:王菲要来西安体育场开演唱会,这个体育场规模不是很大,能容纳1000个人,于是准备了1000张票,后天中午12点在 ...
- Practical Java 摘录(四)--多线程
1)面对instance函数,synchronized锁定的是对象(object)而不是方法(method)或者代码(code) 对于instance函数,关键字其实并不锁定函数或者代码,它锁定的是对 ...
- (四)Java中的多线程之间实现同步+多线程并发同步
一.什么是线程安全问题 为什么有线程安全问题? 当多个线程同时共享同一个全局变量或静态变量,做写的操作(修改变量值)时,可能会发生数据冲突问题,也就是线程安全问题.但是做读操作时不会发生数据冲突问题. ...
- java铃声_java多线程抓取铃声多多官网的铃声数据
一直想练习下java多线程抓取数据. 有天被我发现,铃声多多的官网(http://www.shoujiduoduo.com/main/)有大量的数据. 通过观察他们前端获取铃声数据的ajax http ...
- 【二十四】springboot使用EasyExcel和线程池实现多线程导入Excel数据
springboot篇章整体栏目: [一]springboot整合swagger(超详细 [二]springboot整合swagger(自定义)(超详细) [三]springboot整合toke ...
- java使用多线程查询大批量数据
前言 在某些时候,一旦单表数据量过大,查询数据的时候就会变得异常卡顿,虽然在大多数情况下并不需要查询所有的数据,而是通过分页或缓存的形式去减少或者避免这个问题,但是仍然存在需要这样的场景,比如需要导出 ...
- Java并发与多线程
1.多线程优点 资源利用率更好:文件读写操作 程序设计在某些情况下更简单: 程序响应更快:端口监听操作 2.多线程的代价 设计更复杂:多线程共享数据时尤其需要注意 上下文切换的开销: CPU 会在一个 ...
- java基础学习-多线程笔记
说说Java中实现多线程有几种方法 创建线程的常用三种方式: 1. 继承Thread类 2. 实现Runnable接口 3. 实现Callable接口( JDK1.5>= ) 4. 线程池方式创 ...
- JAVA 笔记 10 多线程
进程 与 线程 进程 进程资源分配的最小单位,CPU从磁盘中读取一段程序到内存中,该执行程序的实例就叫做进程; 一个程序如果被CPU多次读取到内存中,则变成多个独立的进程. 线程 线程是程序执行的最小 ...
最新文章
- 两张图看懂GC 日志
- NLP模型超越人类水平?你可能碰到了大忽悠
- 设置网络映射后,电脑重启后自动重连
- 编程之美求二进制数中1的个数扩展题
- Framelayout
- android -上传文件到服务器
- MDK升级后的头文件冲突
- 第三章 中间件,3.1 万亿级数据洪峰下的分布式消息引擎(作者:冯嘉、誓嘉、尘央、牟羽)...
- 将DataRow转换为DataTable
- 算数计算机在线应用,数学计算器
- 如何造数据——分分钟变成造数据大师
- js基础---字符串方法
- c++ 远程监控软件
- 图像预处理流程与方法
- python3-关于GitHub的最基本操作
- 数据可视化—随机漫步
- P1125 [NOIP2008 提高组] 笨小猴
- VR看房项目总结(1)
- 将.pyc反编译成.py
- 人民币小写转大写算法
热门文章
- vsftp匿名访问目录_怎么更改vsftp匿名用户的默认登录目录/var/ftp?
- html 元素换行_超文本标记语言的段落与换行显示!
- 【Spring第七篇】Java配置类:JavaConfig
- AWT_事件监听2(Java)
- border-radius导致overflow:auto 或者 overflow:hidden失效,溢出问题解决方法
- 森林怎么训练野人_第五人格:野人技能曝光!野猪可以骑,庄园中或将迎来新玩法!...
- linux安装tomcat_Linux云服务器安装jdk、Tomcat、MySQL5.7 - 咸鱼落成
- ORACLE常用监控语句(未完待续)
- context:annotation-config、context:component-scan
- 列表推导式 生成器表达式