java多线程与线程并发四:线程范围内的共享数据
当多个线程操作同一个共有数据时,一个线程对共有数据的改变会影响到另一个线程。比如下面这个例子:两个线程调用同一个对象的的方法,一个线程的执行结果会影响另一个线程。
package com.sky.thread; public class TestThreadLocal {
public static void main(String[] args) {
final ThreadLocalBiz biz = new ThreadLocalBiz();
new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
biz.add(); }
}
}).start();
new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
biz.add(); }
}
}).start();
}
} class ThreadLocalBiz {
private int num = 0; public synchronized void add() {
num++;
System.out.println("线程:" + Thread.currentThread().getName() + "num:"
+ num);
}
}
线程结果互相影响
执行的结果是:
线程:Thread-0num:1
线程:Thread-1num:2
线程:Thread-0num:3
线程:Thread-1num:4
执行结果
可见,Thread-0执行完以后,num的值是1。当Thread-1开始执行时,num的值对它而言是1而不是一开始的0,所以在Thread-1执行完以后,num的值变成了2。
如果我们想让两个线程在操作同一个共有数据时,互相的操作结果互不影响该怎么办?
这个时候可以使用ThreadLocal。先看下面的代码:
package com.sky.thread; public class TestThreadLocal { public static void main(String[] args) {
new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} ThreadLocalBiz.getBiz().add(); }
}
}).start();
new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} ThreadLocalBiz.getBiz().add(); }
}
}).start();
}
} class ThreadLocalBiz {
private int num = 0;
public static ThreadLocal<ThreadLocalBiz> LocalBiz = new ThreadLocal<ThreadLocalBiz>(); private ThreadLocalBiz(){}
public static ThreadLocalBiz getBiz(){
ThreadLocalBiz biz = LocalBiz.get();
if (biz == null) {
biz = new ThreadLocalBiz();
LocalBiz.set(biz);
}
return biz;
}
public void add() {
num++;
System.out.println("线程:" + Thread.currentThread().getName() + ",num:"
+ num);
} }
线程:Thread-0,num:1
线程:Thread-1,num:1
线程:Thread-0,num:2
线程:Thread-0,num:3
线程:Thread-1,num:2
执行结果
这段代码的基本思路是,为不同的线程创建单独的实例。比如上面这段代码,有两个线程调用的ThreadLocalBiz的add方法,那么一共创建的两个ThreadLocalBiz实例。每个线程操作自己的专属实例,自然就不会相互干扰了。
在这段代码中,getBiz和add方法都没有加synchronized,就是因为单个实例只对应单个线程,不存在并发问题,自然也就不用加互斥锁了。
现在来仔细说说ThreadLocal。
ThreadLocal相当于一个Map。以当前线程作为key。
下面的代码
ThreadLocal<ThreadLocalBiz> LocalBiz = new ThreadLocal<ThreadLocalBiz>();
LocalBiz.set(new ThreadLocalBiz());
LocalBiz.get();
就相当于
Map<Thread, ThreadLocalBiz> ThreadMap = new HashMap<Thread, ThreadLocalBiz>();
ThreadMap.put(Thread.currentThread(), new ThreadLocalBiz());
ThreadMap.get(Thread.currentThread());
可见,ThreadLocal完全可以被Map代替。java只是代为封装了一下。
java多线程与线程并发四:线程范围内的共享数据的更多相关文章
- “全栈2019”Java多线程第三十四章:超时自动唤醒被等待的线程
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java多线程学习(八)线程池与Executor 框架
目录 历史优质文章推荐: 目录: 一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 2.3 Executor 框架的使用示意图 ...
- Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...
- Java 多线程基础(五)线程同步
Java 多线程基础(五)线程同步 当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题. 要解决上述多线程并发访问一个资源的安全性问题,Java中提供了同步机制 ...
- Java多线程基础:进程和线程之由来
转载: Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够 ...
- “全栈2019”Java多线程第十三章:线程组ThreadGroup详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 1、Java多线程基础:进程和线程之由来
Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ...
- Java 多线程基础(六)线程等待与唤醒
Java 多线程基础(六)线程等待与唤醒 遇到这样一个场景,当某线程里面的逻辑需要等待异步处理结果返回后才能继续执行.或者说想要把一个异步的操作封装成一个同步的过程.这里就用到了线程等待唤醒机制. 一 ...
- Java 多线程基础(十一)线程优先级和守护线程
Java 多线程基础(十一)线程优先级和守护线程 一.线程优先级 Java 提供了一个线程调度器来监控程序启动后进去就绪状态的所有线程.线程调度器通过线程的优先级来决定调度哪些线程执行.一般来说,Ja ...
- Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型
http://blog.csdn.net/a352193394/article/details/39503857 Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会 ...
随机推荐
- Liang-Barsky算法
Liang-Barsky算法 在Cohen-Sutherland算法提出后,梁友栋和Barsky又针对标准矩形窗口提出了更快的Liang-Barsky直线段裁剪算法. 梁算法的主要思想: (1)用参数 ...
- Flask框架整个流程源码解读
Flask框架整个流程源码解读 一.总的流程 运行Flask其本质是运行Flask对象中的__call__,而__call__本质调用wsgi_app的方法 wsgi_app方法 def wsgi_a ...
- Jsoup-解析HTML工具(简单爬虫工具)
Jsoup-解析HTML工具(简单爬虫工具) 一.简介 jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS ...
- Neo4j:图数据库GraphDB(四)Python中的操作
本文总结下Python中如何操作Neo4j数据库,用到py2neo包,Pip install 一下. 1 连接neo4j数据库:跟其它数据库一样,操作前必须输入用户名和密码及地址连接一下. from ...
- Redis 3.0中文版学习(一)
网址:http://wiki.jikexueyuan.com/project/redis-guide/entry-to-master-a.html http://www.yiibai.com/redi ...
- JavaScript回调函数和递归函数
一.回调函数--通过函数的指针来调用函数 把一个函数的指针作为另一个函数的参数,当调用这个参数的时候,这个函数就叫做回调函数 在链式运动上会用到回调函数,之后运动会见到 A.通过指针来调用函数 B.通 ...
- [NOIp2014] luogu P1351 联合权值
哎我博 4 了. 题目描述 无向连通图 GGG 有 nnn 个点,n−1n−1n−1 条边.点从 111 到 nnn 依次编号,编号为 iii 的点的权值为 WiW_iWi,每条边的长度均为 111 ...
- springboot Jar包 部署到Linux服务器运行脚本
1.jar包同级目录 , 如下: #!/bin/sh RESOURCE_NAME=demo.jar tpid=`ps -ef|grep $RESOURCE_NAME|grep -v grep|grep ...
- python中的随机函数
python--随机函数(random,uniform,randint,randrange,shuffle,sample) 本文转载自:[chamie] random() random()方法:返回随 ...
- {每日一题}:四种方法实现打印feibo斐波那契数列
刚开始学Python的时候,记得经常遇到打印斐波那契数列了,今天玩玩使用四种办法打印出斐波那契数列 方法一:使用普通函数 def feibo(n): """ 打印斐波那契 ...