- 浏览: 460103 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (369)
- javascript html (20)
- java (31)
- jquery (15)
- jcrop (0)
- JEECG (1)
- ajax (3)
- 反射 (3)
- VI (1)
- mysql (48)
- easyui (1)
- svn (2)
- MD5 加密 (1)
- spring (14)
- ORACLE (8)
- 经验总结 (1)
- TCP/IP协议 (1)
- ICMP协议 (1)
- eclipse (1)
- Reflect (1)
- linux (21)
- android (5)
- excel 操作 (1)
- java tree (1)
- html (1)
- plupload (1)
- mongodb (9)
- aes (1)
- python (1)
- java relax (1)
- highcharts (2)
- json (2)
- java 多线程 (30)
- maven (2)
- 设计模式 (1)
- jsp+js (2)
- 面向对象 (1)
- jvm (16)
- 缓存 (1)
- proxy (1)
- 聊侃 (1)
- 面经 (1)
- java 字节 (1)
- java 类加载器 (2)
- java 基础 (2)
- java 语法糖 (1)
- java 位运算 (1)
- 排序 (3)
- java 服务器性能优化 (19)
- 网络编程 (2)
- jvm 参数设置 (0)
- jersey (1)
- webservice (2)
- nginx+多tomcat 集成 (5)
- nginx (16)
- squid (3)
- memcached (5)
- 正则表达式 (1)
- 常用免费接口 (1)
- jpa (1)
- win7 (1)
- java处理大文件 (1)
- js正则表达式 (1)
- tomcat (1)
- java 敏感字 (1)
- 系统架构优化 (4)
- 学习 (1)
- 本地测试QQ微博第三方登陆 (1)
- java 错误 (1)
- 微信支付 (1)
- https (1)
- httpclient (1)
- awk (2)
- loadrunner (1)
- sql server 2008 (3)
- git (4)
- sql server2008 (1)
- solr (2)
- centos (1)
- 数据存储架构 (3)
- log4j (1)
- weboffice (1)
- 并发编程 (1)
- postgreSQL (0)
- ssl (1)
- openssl (1)
- activeMQ (2)
- IDEA (1)
- shell (1)
- ansible (4)
- docker (2)
- grafana (1)
- jmeter (1)
- TLS (1)
- 将博客搬至CSDN (1)
最新评论
-
dida1990:
啊喔,过去了这么久,不过还是评一个。谁说uuid的hashCo ...
高并发生成订单号(二) -
annan211:
yclovesun 写道使用了uuid,为什么还要machin ...
高并发生成订单号(二) -
yclovesun:
使用了uuid,为什么还要machineId?uuid已经可以 ...
高并发生成订单号(二) -
u013280917:
太深奥,看不懂
mysql优化特定类型的查询
Java 线程范围内的数据共享机制,需要解决的问题是 : 多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象
实例 A B 两个类 需要操作同一个static变量 data
初步代码 可能如下:
执行结果:
分析结果可以看出 线程0 赋值数据 350455289,线程1 赋值数据 -1313940209,模块AB 拿到的data 却只是线程1 赋值的结果,这就说明在线程 0 赋值之后,AB操作之前,线程1 就已经将data的值修改为 -1313940209 了。
简单一点的修改 可以如下:
结果如下
将数据与当前线程相挂钩的话 那么显然是可以利用ThreadLocal这个类
ThreadLocal 就相当于一个 Map,key就是当前线程,value为当前线程对应的值, 那么改造上面的代码得到下面的代码:
代码执行完以后会得到同样的效果。
接下来还有一个问题 上面一直讨论的是线程间共享一个变量 那么如果是多个变量呢?
要直接ThreadLocal每次只能是一个变量和当前线程挂钩 如果有多个变量要和当前线程挂钩的话 就得生命多个ThreadLocal对象 这样子做很显然是不合理的。那如何处理呢?
由于ThreadLocal可以并且只能和一个变量挂钩,那么我们可以将这个变量设置为一个变量的容器,容器中可以存在多个变量,这也就是将需要和当前线程绑定的变量封装到一个实体类中
ThreadLocal 是并发程序的一种解决方案,他利用空间换时间,也就是为每个线程分配空间来实现多线程,ThreadLocal 完全不使用锁,因此他不是一种数据共享的锁。
从性能上来说,ThreadLocal 并不具备绝对的优势,但是作为一种完全不使用锁的多线程解决方案,在高并发的情况下,在一定程度上可以减少锁的竞争。
实例 A B 两个类 需要操作同一个static变量 data
初步代码 可能如下:
package threadLocal; import java.util.HashMap; import java.util.Map; import java.util.Random; /** * 线程范围内的共享数据 * @author jingfn * */ public class ThreadScopeShareDate { private static int data ; public static void main(String[] args) { for(int i=0;i<2;i++) new Thread(new Runnable(){ public void run(){ data = new Random().nextInt(); System.out.println(Thread.currentThread().getName()+"--put data "+data); new A().get(); new B().get(); } }).start(); } static class A{ private void get(){ System.out.println("A--get data from "+Thread.currentThread().getName()+" of "+data); } } static class B{ private void get(){ System.out.println("B--get data from "+Thread.currentThread().getName()+" of "+data); } } }
执行结果:
Thread-0--put data 350455289 Thread-1--put data -1313940209 A--get data from Thread-0 of -1313940209 A--get data from Thread-1 of -1313940209 B--get data from Thread-1 of -1313940209 B--get data from Thread-0 of -1313940209
分析结果可以看出 线程0 赋值数据 350455289,线程1 赋值数据 -1313940209,模块AB 拿到的data 却只是线程1 赋值的结果,这就说明在线程 0 赋值之后,AB操作之前,线程1 就已经将data的值修改为 -1313940209 了。
简单一点的修改 可以如下:
package threadLocal; import java.util.Random; /** * 线程范围内的共享数据 * @author jingfn * */ public class ThreadScopeShareDate { private static int data ; public static void main(String[] args) { for(int i=0;i<2;i++) new Thread(new Runnable(){ public void run(){ synchronized(ThreadScopeShareDate.class){ data = new Random().nextInt(); System.out.println(Thread.currentThread().getName()+"--put data "+data); new A().get(); new B().get(); } } }).start(); } static class A{ private void get(){ System.out.println("A--get data from "+Thread.currentThread().getName()+" of "+data); } } static class B{ private void get(){ System.out.println("B--get data from "+Thread.currentThread().getName()+" of "+data); } } }
结果如下
Thread-0--put data -30716152 A--get data from Thread-0 of -30716152 B--get data from Thread-0 of -30716152 Thread-1--put data 913737008 A--get data from Thread-1 of 913737008 B--get data from Thread-1 of 913737008
将数据与当前线程相挂钩的话 那么显然是可以利用ThreadLocal这个类
ThreadLocal 就相当于一个 Map,key就是当前线程,value为当前线程对应的值, 那么改造上面的代码得到下面的代码:
package threadLocal; import java.util.Random; /** * 线程范围内的共享数据 * @author jingfn * */ public class ThreadScopeShareDate { private static int data ; private static ThreadLocal<Integer> localdata = new ThreadLocal<Integer>(); public static void main(String[] args) { for(int i=0;i<2;i++) new Thread(new Runnable(){ public void run(){ synchronized(ThreadScopeShareDate.class){ data = new Random().nextInt(); localdata.set(data); System.out.println(Thread.currentThread().getName()+"--put data "+data); new A().get(); new B().get(); } } }).start(); } static class A{ private void get(){ System.out.println("A--get data from "+Thread.currentThread().getName()+" of "+localdata.get()); } } static class B{ private void get(){ System.out.println("B--get data from "+Thread.currentThread().getName()+" of "+localdata.get()); } } }
代码执行完以后会得到同样的效果。
接下来还有一个问题 上面一直讨论的是线程间共享一个变量 那么如果是多个变量呢?
要直接ThreadLocal每次只能是一个变量和当前线程挂钩 如果有多个变量要和当前线程挂钩的话 就得生命多个ThreadLocal对象 这样子做很显然是不合理的。那如何处理呢?
由于ThreadLocal可以并且只能和一个变量挂钩,那么我们可以将这个变量设置为一个变量的容器,容器中可以存在多个变量,这也就是将需要和当前线程绑定的变量封装到一个实体类中
package threadLocal; import java.util.Random; /** * 线程范围内的共享数据 * @author jingfn * */ public class ThreadScopeShareDateContainer { private static int data ; public static void main(String[] args) { for(int i=0;i<2;i++) new Thread(new Runnable(){ public void run(){ synchronized(ThreadScopeShareDateContainer.class){ data = new Random().nextInt(); Container.getInstance().setData1(data); Container.getInstance().setData2(data); System.out.println(Thread.currentThread().getName()+"--put data "+data); new A().get(); new B().get(); } } }).start(); } static class A{ private void get(){ System.out.println("A--get data from "+Thread.currentThread().getName()+" of "+Container.getInstance().getData1()+"--"+Container.getInstance().getData2()); } } static class B{ private void get(){ System.out.println("B--get data from "+Thread.currentThread().getName()+" of "+Container.getInstance().getData1()+"--"+Container.getInstance().getData2()); } } } class Container{ private int data1,data2; private static ThreadLocal<Container> local = new ThreadLocal<Container>(); public static Container getInstance(){ Container container = local.get();; if(container == null){ container = new Container(); local.set(container); } return container; } public int getData1() { return data1; } public void setData1(int data1) { this.data1 = data1; } public int getData2() { return data2; } public void setData2(int data2) { this.data2 = data2; } }
ThreadLocal 是并发程序的一种解决方案,他利用空间换时间,也就是为每个线程分配空间来实现多线程,ThreadLocal 完全不使用锁,因此他不是一种数据共享的锁。
从性能上来说,ThreadLocal 并不具备绝对的优势,但是作为一种完全不使用锁的多线程解决方案,在高并发的情况下,在一定程度上可以减少锁的竞争。
发表评论
-
java 多线程操作数据库 及 静态bean注入
2018-01-09 10:47 912package com.robustel.rlink.de ... -
Amino 框架简介
2014-10-17 11:30 1425对数据加锁是实现多线程的一种策略,但是加锁无疑会增加系 ... -
Java 重入锁(ReentrantLock)和内部锁(synchronized)
2014-10-16 15:44 1591ReentrantLock 和 synchronize的 ... -
Java 锁分离
2014-10-16 15:35 1331读写锁思想的延伸就是锁分离。读写锁根据读写操作功能上 ... -
java 高性能运算-- 双端队列
2014-10-15 16:04 1042JDK 1.6中 提供了一种双端队列,简称 Dequ ... -
java 高性能运算--并发队列
2014-10-15 15:33 2486JDK 提供了两套并发队列的实现,一个是以 Conc ... -
并发模式下的单例创建
2014-09-29 16:20 784单例模式的创建 分为 ... -
Java 同步集合的应用
2014-09-14 23:45 0Java 同步集合的应用 -
java 阻塞队列的应用
2014-09-14 23:44 0java 阻塞队列的应用 -
java 多线程集合
2014-09-14 23:28 0java 多线程集合 -
java Exchanger 线程数据交换
2014-09-14 22:56 0java Exchanger 线程数据交换 -
java CountDownLatch 实例
2014-09-15 18:07 848Java的concurrent包里面的CountDownLat ... -
java 多线程之 CyclicBarrier
2014-09-13 19:25 815CyclicBarrier (周期障碍)类可以帮助同步,它允许 ... -
java CyclicBarrier 循环阻塞
2014-09-12 22:43 434java CyclicBarrier 循环阻塞 -
java 多线程的锁消除
2014-09-12 18:31 1241Java 中使用同步 来保证数据的安全性,但是对于一些明显不会 ... -
java锁的种类以及辨析(一):自旋锁
2014-09-12 16:22 1628Java的多线程安全是基于Lock机制(或者隐式锁synchr ... -
Java锁的种类以及辨析
2014-09-12 15:15 1573锁作为并发共享数据,保证一致性的工具,在java平台有多种实现 ... -
java Semaphore 信号量详解和实例
2014-09-12 11:51 2150生产者线程用于往链表里添加节点,数个工作线程从链表取出节点并处 ... -
4个线程,2个每次加1,两个每次减1
2014-09-01 23:44 849package threadTest; public ... -
java多线程之Semaphore信号量详解
2014-08-27 13:35 1306原创作品,允许转载,转载时请务必以超链接形式标明文章 原始 ...
相关推荐
- **概念**:线程范围内共享变量是指在线程间共享的数据,需小心处理以避免竞态条件和数据不一致性。 - **作用**:允许线程间通信和协作,但需采用适当的同步机制(如`synchronized`关键字、`Lock`接口)以确保数据...
为了避免多个线程同时访问共享资源造成的数据不一致,Java 提供了多种同步机制,包括: 1. synchronized 关键字:可以修饰方法或代码块,确保同一时间只有一个线程可以执行特定的代码。 2. volatile 关键字:保证了...
`Example`类提供了丰富的API来构建复杂的查询条件,如 `createCriteria()` 用于创建一个新的 Criteria 实例,`and...Between(...)` 用于添加年龄在给定范围内的条件,以及 `clear()` 用于清除所有已设置的条件。...
当多个线程只需要读取共享数据时,它们可以同时持有读锁,而不会阻塞彼此。只有在写操作发生时,才会阻止其他读或写操作。 - 可重入性:持有读锁或写锁的线程可以再次获取同一类型的锁,而不会导致死锁。 - 读写锁...
2. **避免使用实例变量**:尽可能将状态信息存储在请求或会话范围内,这样每个请求或会话都有自己独立的数据,不会互相干扰。 3. **ThreadLocal变量**:对于需要在多线程环境中保持独立状态的变量,可以使用`...
线程总是属于某个进程,并且同一进程内的多个线程共享该进程的内存资源。 **2. Java中的线程** 在Java中,“线程”主要涉及两个方面: - **java.lang.Thread类的实例**:表示线程对象,拥有自己的变量和方法,...
### Java并发编程与多线程知识点详解 #### 1. 线程安全与锁定机制 - **确保线程安全**: 在Java并发编程中,确保线程安全是至关重要的。通常有三种方法来实现这一点: - 使用`synchronized`关键字:这是最基本的...
- `ThreadLocal` 不适用于解决多个线程间的共享数据问题,主要用于在线程内部保存数据。 - 在使用 `ThreadLocal` 时需注意显式地清理不再使用的变量,尤其是当线程可能重用时。 #### 三、MVCC(多版本并发控制) *...
线程范围内共享变量的概念与作用 - 线程范围内的共享变量是指多个线程可以访问同一个变量,需要注意线程安全。 ##### 6. ThreadLocal类及应用技巧 - `ThreadLocal`类提供了一种线程局部变量的解决方案,可以为每个...
- **线程本地存储(ThreadLocal)**:通过`ThreadLocal`类,可以为每个线程提供独立的变量副本,避免了线程间的共享数据竞争。 #### 四、Java并发编程的最佳实践 为了有效地利用Java的并发特性,开发人员应该遵循...
`ThreadLocal`为每个使用该变量的线程提供独立的副本,线程之间不会相互干扰,从而解决了多线程之间的数据共享问题。 #### 3. 避免过度同步 过度同步会导致性能下降,因此在设计时应尽量减少同步操作。例如,可以...
**ServletContext**是一个全局共享的对象,用于存储应用程序范围内的数据。它是在Servlet容器启动时创建的,并在整个应用的生命周期内一直存在。`ServletContext`的主要用途有: - 存储全局属性和初始化参数。 - ...
- **volatile**:用于修饰共享变量,确保多线程环境中的可见性和有序性,但不保证原子性。 - **synchronized**:用于实现同步控制,可以修饰方法或代码块,保证同一时间只有一个线程执行该段代码。 - **import**:...
### Java高频面试知识点详解 #### 一、Java基础 **1. JDK和JRE有什么区别?** - **JRE(Java Runtime Environment)**: 包含Java虚拟机(JVM)、Java核心类库和支持文件,是运行Java程序所需的基础环境。 - **JDK...
- **getAttribute()**:用于获取请求范围内存储的任意属性。 #### 26. Cookie 的获取与设置 - **获取 Cookie**:通过 HttpServletRequest 对象的 `getCookies()` 方法。 - **设置 Cookie**:通过 ...
- **page**:当前页面范围内有效。 - **request**:客户端一次请求有效。 - **session**:用户会话期间有效。 - **application**:整个Web应用有效。 ##### List, Set, Collection, Collections - **Collection**...
2.2.4. 堆(Heap-线程共享)-运行时数据区 ...................................................................................... 23 2.2.5. 方法区/永久代(线程共享) ............................................