Java中String做为synchronized同步锁
synchronized (("" + userId).intern()) {
// TODO:something
}
JVM内存区域里面有一块常量池,关于常量池的分配:
- JDK6的版本,常量池在持久代PermGen中分配
- JDK7的版本,常量池在堆Heap中分配
字符串是存储在常量池中的,有两种类型的字符串数据会存储在常量池中:
- 编译期就可以确定的字符串,即使用""引起来的字符串,比如String a = "123"、String b = "1" + B.getStringDataFromDB() + "2" + C.getStringDataFromDB()、这里的"123"、"1"、"2"都是编译期间就可以确定的字符串,因此会放入常量池,而B.getStringDataFromDB()、C.getStringDataFromDB()这两个数据由于编译期间无法确定,因此它们是在堆上进行分配的
- 使用String的intern()方法操作的字符串,比如String b = B.getStringDataFromDB().intern(),尽管B.getStringDataFromDB()方法拿到的字符串是在堆上分配的,但是由于后面加入了intern(),因此B.getStringDataFromDB()方法的结果,会写入常量池中
常量池中的String数据有一个特点:每次取数据的时候,如果常量池中有,直接拿常量池中的数据;如果常量池中没有,将数据写入常量池中并返回常量池中的数据。
这个在jdk6里问题不算大,因为String.intern()会在perm里产生空间,如果perm空间够用的话,这个不会导致频繁Full GC,
但是在jdk7里问题就大了,String.intern()会在heap里产生空间,而且还是老年代,如果对象一多就会导致Full GC时间超长!!!
慎用啊!解决办法?终于找到了。
这里要引用强大的google-guava包,这个包不是一般的强大,是完全要把apache-commons*取缔掉的节奏啊!!!
Interner<String> pool = Interners.newWeakInterner(); synchronized ( pool.intern("BizCode"+userId)){ //TODO:something }
该类对 intern 做了很多的优化,使用弱引用包装了你传入的字符串类型,所以,这样就不会对内存造成较大的影响, 可以使用该类的 pool.intern(str) 来进行对字符串intern, 好了,这样就解决了内存的问题了,那么我们使用了该优点,并且避免了内存占用问题,完美解决。但这种在分布式系统中会有问题
//类1- SynStringTest
package com.tinygao.thread.synstring; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer; import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import lombok.extern.slf4j.Slf4j; @Slf4j
public class SynStringTest { private final static SynString synStr = new SynString();
private final static Stopwatch sw = Stopwatch.createStarted();
private static BiConsumer<SynString, String> function = (x, y)->{
synchronized (x.getStringLock(y)) {
log.info("Get lock: {}", y);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
public static void main(String[] args) throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(
4,
new ThreadFactoryBuilder().setNameFormat("SynString-%d").build()
); executorService.submit(()->{
doTask("test");
});
executorService.submit(()->{
doTask("test");
});
executorService.submit(()->{
doTask("test1");
});
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
sw.stop();
} private static void doTask(String lockStr) {
function.accept(synStr, lockStr);
log.info("Do get lockStr successed waste time elapsed : {} ms", sw.elapsed(TimeUnit.MILLISECONDS));
}
} //类2- SynString
package com.tinygao.thread.synstring;
import java.util.concurrent.ConcurrentMap;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j; @Slf4j
public class SynString { private static ConcurrentMap<String,Object> parMap = Maps.newConcurrentMap(); public Object getStringLock(String string) {
Object lock = this;
if(parMap != null) {
Object newLock = new Object();
lock = parMap.putIfAbsent(string, newLock);
if(lock == null) {
lock = newLock;
}
}
return lock;
} public static void main(String[] args) {
Object result = parMap.putIfAbsent("h", "g");
log.info("Get result: {}", result);
}
}
Java中String做为synchronized同步锁的更多相关文章
- Java中String做为synchronized同步锁使用详解
Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...
- Java中使用CountDownLatch进行多线程同步
CountDownLatch介绍 在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法: 1.synchronized关键字进行同步. 2.Lock锁接口及其实现类ReentrantL ...
- java中String、StringBuffer、StringBuilder的区别
java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题.现在总结一下,看看他们的不同与相同. 1.可变与不可 ...
- java中String类型变量的赋值问题
第一节 String类型的方法参数 运行下面这段代码,其结果是什么? package com.test; public class Example { String str = new String( ...
- Java基础知识(JAVA中String、StringBuffer、StringBuilder类的区别)
java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题.现在总结一下,看看他们的不同与相同. 1.可变与不可 ...
- Java基础——java中String、StringBuffer、StringBuilder的区别
(转自:http://www.cnblogs.com/xudong-bupt/p/3961159.html) java中String.StringBuffer.StringBuilder是编程中经常使 ...
- 探秘Java中String、StringBuilder以及StringBuffer
探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...
- java中String类、StringBuilder类和StringBuffer类详解
本位转载自http://www.cnblogs.com/dolphin0520/p/3778589.html 版权声明如下: 作者:海子 出处:http://www.cnblogs.com/dolp ...
- 【转载】 Java中String类型的两种创建方式
本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...
随机推荐
- MyBatis中jdbcType=INTEGER、VARCHAR作用
Mapper.xml中 pid = #{pid,jdbcType=INTEGER} pid = #{pid} 都可以用 Mybatis中什么时候应该声明jdbcType? 当Mybatis不能自动识别 ...
- [报错解决] "MySQL server has gone away" 解决思路
大概的4个思路 1.超时,超时的阀值有wait_timeout这个参数控制 2.连接被人为的kill 3.发送的SQL语句过大超过max_allowed_packet的大小. (操作的sql语句太长了 ...
- P1338 末日的传说,P1372 P1414 又是毕业季——贪心
一个1到n序列,合理排序逆序对数要求是m,而且字典序要求最小: 这个题,因为数字只能用一次,所以我们可以知道什么位置放什么数逆序对的个数会增加或减少多少: 先求出最多能产生的数量,每次先输出最小的数, ...
- cas系列-cas登出(四)
跟登陆一样,登出操作也很重要.由于是多应用间操作,状态保持也是一个要点,根据登出的影响范围,可以将登出操作分为两类: 单应用登出 单点登出(多应用登出) 顾名思义,单应用登出即登出只影响被操作的应用会 ...
- (转)SmartPing:一个服务器Ping值监测工具
官网:https://docs.smartping.org/ 借鉴:https://www.moerats.com/archives/710/ 说明:之前博主发过一个雨落大神写的Ping值监测工具uP ...
- ShardingSphere Hint模式 SpringBoot + Mybatis
ShardingSphere Hint模式不需要对sql进行解析,就可以进行数据库或者表的路由.下面贴一下代码,关于SpringBoot + Mybatis + ShardingSphere怎样结合. ...
- 深入理解WebRTC
Web Real-Time Communication(Web实时通信,WebRTC)由一组标准.协议和JavaScript API组成,用于实现浏览器之间(端到端)的音频.视频及数据共享. WebR ...
- 判断 js 类型的方式
1. typeof 可以判断出'string','number','boolean','undefined','symbol'但判断 typeof(null) 时值为 'object'; 判断数组和对 ...
- OpenJudge计算概论-数组逆序重放
/*=============================================================== 数组逆序重放 总时间限制: 1000ms 内存限制: 65536kB ...
- 【精华】PHP网站验证码不显示的终结解决方案
PHP网站验证码不显示,这个是个很基础的PHP问题了,不过有点时候会比较让开发者比较头疼了.很多解决方案仅仅考虑到gd2,却忽略了另外一个很重要的因素了,相信在了解本教程之后,验证码不显示基本上就不算 ...