Java中的线程--线程范围内共享数据
接着学习Java中的线程,线程范围内的共享数据!
一、线程范围内的数据共享定义
对于相同的程序代码,多个模块在同一个线程中共享一份数据,而在另外线程中运行时又共享另外一份数据。
共享数据中存在的问题,代码如下:
// A 和 B共享数据data,但是在这种情况下 会存在问题
public class ThreadScopeShareData { private static int data = 0; public static void main(String[] args) {
for (int i = 0; i < 10; 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 void get() {
System.out.println("A from " + Thread.currentThread().getName() + "has put data " + data);
}
} static class B {
public void get() {
System.out.println("B from " + Thread.currentThread().getName() + "has put data " + data);
}
} }
运行结果如下:(好像是有点乱七八糟的感觉)
Thread-3has put data 1233171571
Thread-7has put data -1796246182
Thread-1has put data -609826403
A from Thread-3has put data 1961867182
A from Thread-1has put data 1961867182
Thread-8has put data 2116621494
A from Thread-8has put data 1961867182
Thread-5has put data -609826403
A from Thread-5has put data 1961867182
A from Thread-7has put data 1961867182
B from Thread-7has put data 1961867182
B from Thread-5has put data 1961867182
Thread-6has put data -609826403
A from Thread-6has put data 1961867182
B from Thread-6has put data 1961867182
Thread-0has put data 1233171571
A from Thread-0has put data 1961867182
B from Thread-0has put data 1961867182
Thread-9has put data 1961867182
A from Thread-9has put data 1961867182
B from Thread-9has put data 1961867182
B from Thread-1has put data 1961867182
Thread-2has put data 1233171571
Thread-4has put data 1233171571
A from Thread-4has put data 1961867182
B from Thread-4has put data 1961867182
B from Thread-8has put data 1961867182
B from Thread-3has put data 1961867182
A from Thread-2has put data 1961867182
B from Thread-2has put data 1961867182
解决方案如下,用线程范围内的变量,当然这个是比较粗糙的解决方案,代码如下:
public class ThreadScopeShareData { private static int data = 0;
// 这个用来存放当前线程内的共享数据
private static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>(); public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + "has put data " + data);
threadData.put(Thread.currentThread(), data);
new A().get();
new B().get();
}
}).start();
}
} static class A {
public void get() {
int data = threadData.get(Thread.currentThread());
System.out.println("A from " + Thread.currentThread().getName() + "has put data " + data);
}
} static class B {
public void get() {
int data = threadData.get(Thread.currentThread());
System.out.println("B from " + Thread.currentThread().getName() + "has put data " + data);
}
} }
二、JDK中解决线程共享数据(ThreadLocal)
优化解决方法,更加优雅的代码,更加人性化的解决方法,使得用户用起来更加方便,封装到ThreadLocal中,并且得保证同一个线程,所得到的的是同一份数据!
改造之后的实体对象,代码如下:
// 改造之后的实体类,封装创建方法,并且封装ThreadLocal,来保证同一个线程得到的同一个对象
public class MyThreadScopeData { private String name;
private int age;
//private static MyThreadScopeData instance = null;
private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>(); private MyThreadScopeData() { } public static /* synchronized */ MyThreadScopeData getThreadInstance() {
MyThreadScopeData instance = map.get();
if(instance == null) {
instance = new MyThreadScopeData();
map.set(instance);
}
return instance;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} }
测试类中代码如下:
public class ThreadLocalTest { private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
private static ThreadLocal<MyThreadScopeData> myThreadLocal = new ThreadLocal<MyThreadScopeData>(); public static void main(String[] args) {
// 相当于创建了10个线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + "has put data " + data);
// MyThreadScopeData myData = new MyThreadScopeData();
// myData.setName("name" + data);
// myData.setAge(data);
// myThreadLocal.set(myData); MyThreadScopeData.getThreadInstance().setName("name" + data);
MyThreadScopeData.getThreadInstance().setAge(data);
// 存放的是与当前线程相关的数据
x.set(data); new A().get();
new B().get();
}
}).start();
}
} static class A {
public void get() {
int data = x.get();
System.out.println("A from " + Thread.currentThread().getName() + "has get data " + data); // MyThreadScopeData myData = myThreadLocal.get();
// System.out.println("A from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","
// + myData.getAge()); MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
System.out.println("A from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","
+ myData.getAge());
}
} static class B {
public void get() {
int data = x.get();
System.out.println("B from " + Thread.currentThread().getName() + "has get data " + data); // MyThreadScopeData myData = myThreadLocal.get();
// System.out.println("B from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","
// + myData.getAge()); MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
System.out.println("B from " + Thread.currentThread().getName() + "has getMyData " + myData.getName() + ","
+ myData.getAge());
}
}
}
总结:这个线程范围内的数据共享问题,解决的方法中用到了单例模式中的设计思想,但是区别的地方是加了一步将数据存放到ThreadLocal 中,实现数据的共享!
三、多线程访问共享数据和线程的方式
也是线程间数据共享的问题,只不过这个是以实战的角度来探索线程共享间数据的同步问题,主要学的是这种解决实际问题的能力,看看代码:
public class MultiThreadShareData { public static void main(String[] args) {
final ShareData1 data1 = new ShareData1(); new Thread(new Runnable() {
@Override
public void run() {
data1.decrement();
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
data1.increment();
}
}).start();
} static class ShareData1 /* implements Runnable */ { private int j = 0;
private int count = 100; public synchronized void increment() {
j++;
} public synchronized void decrement() {
j--;
} /*
* @Override public void run() { while (true) { count--; } }
*/
} }
Java中的线程--线程范围内共享数据的更多相关文章
- Java并发基础06. 线程范围内共享数据
假设现在有个公共的变量 data,有不同的线程都可以去操作它,如果在不同的线程对 data 操作完成后再去取这个 data,那么肯定会出现线程间的数据混乱问题,因为 A 线程在取 data 数据前可能 ...
- Java中的守护线程 & 非守护线程(简介)
Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...
- Java中如何创建线程
Java中如何创建线程 两种方式:1)继承Thread类:2)实现Runnable接口. 1.继承Thread类 继承Thread类,重写run方法,在run方法中定义需要执行的任务. class M ...
- 实现java 中 list集合中有几十万条数据,每100条为一组取出
解决"java 中 list集合中有几十万条数据,每100条为一组取出来如何实现,求代码!!!"的问题. 具体解决方案如下: /** * 实现java 中 list集合中有几十万条 ...
- 【转】asp.net中利用session对象传递、共享数据[session用法]
来自:http://blog.unvs.cn/archives/session-transfer-method.html 下面介绍Asp.net中利用session对象传递.共享数据用法: 1.传递值 ...
- asp.net中利用session对象传递、共享数据[session用法]
下面介绍Asp.net中利用session对象传递.共享数据用法: 1.传递值: 首先定义将一个文本值或单独一个值赋予session,如下: session[“name”]=textbox1.text ...
- Java线程与并发库高级应用-线程范围内共享数据ThreadLocal类
1.线程范围内共享变量 1.1 前奏: 使用一个Map来实现线程范围内共享变量 public class ThreadScopeShareData { static Map<Thread, In ...
- ThreadLocal,Java中特殊的线程绑定机制
在DRP项目中,我们使用了ThreadLocal来创建Connection连接,避免了一直以参数的形式将Connection向下传递(传递connection的目的是由于jdbc事务要求确保使用同一个 ...
- Java-ThreadLocal,Java中特殊的线程绑定机制
在DRP项目中,我们使用了ThreadLocal来创建Connection连接,避免了一直以参数的形式将Connection向下传递(传递connection的目的是由于jdbc事务要求确保使用同一个 ...
随机推荐
- [Xcode 实际操作]七、文件与数据-(21)ARKit增强现实框架的使用
目录:[Swift]Xcode实际操作 本文将演示ARKit增强现实框架的使用. 创建一个新的项目:[Create a new Xcode project] ->在打开的模板选择中,选择增强现实 ...
- Mol Cell Proteomics. |陈洁| 整合鸟枪法蛋白质组学中鉴定和定量的错误率
大家好,本周分享的是发表在MCP上的一篇关于鸟枪蛋白质组学中的错误率的文章,题目是Integrated identification and quantification error probabil ...
- express框架之1
express框架: 1.依赖中间件 2.接受请求 get / post / use get('/地址' , function(req , resp ){}) post和use 同理 3.非破坏式 4 ...
- JDK 重要目录结构
\bin 目录包含 Java 的开发工具,包括 Java 编译器 javac.exe.Java 解释器 java.exe 等: javac:Java 编译器,用来将 Java 程序编译成字节码 jav ...
- Java之多线程同步基础
java学习的道路上呢总有一些麻烦的东西需要花费一些时间去理解,比如个人认为不好搞的多线程. 线程是并列运行的 因为是并列运行,所以有时候会发生资源抢占,从而导致参数变化; 比如酱紫 package ...
- perl 安装LOG4perl 模块
环境信息 ubuntu 12.04 64位 桌面版 Log-Log4perl 的介绍网址:http://search.cpan.org/~mschilli/Log-Log4perl-1.49/lib/ ...
- 计算机网络自顶向下方法第2章-应用层(application-layer).1
2.1 应用层协议原理 2.1.1网络应用程序体系结构 1)在客户-服务器体系结构 (client-server architecture)中,有一个总是打开的主机称为服务器,它服务于来自许多其他称为 ...
- beanutils包下载
- win 7启动tensorboard的详尽步骤
TensorBoard是TensorFlow下的一个可视化的工具,能够帮助我们在训练大规模神经网络过程中出现的复杂且不好理解的运算.TensorBoard能展示你训练过程中绘制的图像.网络结构等. 1 ...
- wawawa8的模板复习计划
wawawa8的模板复习计划 数据结构 //手写堆 [link][https://www.luogu.org/problemnew/show/P3378] //并查集 [link][https://w ...