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 ...
随机推荐
- learning scala generic classes
package com.aura.scala.day01 object genericClasses { def main(args: Array[String]): Unit = { val sta ...
- 【luogu1251】餐巾计划问题--网络流建模,费用流
题目描述 一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同.假设第 iii 天需要 ri块餐巾( i=1,2,...,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部 ...
- 代码 | 自适应大邻域搜索系列之(6) - 判断接受准则SimulatedAnnealing的代码解析
前言 前面三篇文章对大家来说应该很简单吧?不过轻松了这么久,今天再来看点刺激的.关于判断接受准则的代码.其实,判断接受准则有很多种,效果也因代码而异.今天介绍的是模拟退火的判断接受准则.那么,相关的原 ...
- LeetCode 第 150 场周赛
一.拼写单词(LeetCode-1160) 1.1 题目描述 1.2 解题思路 由于给定的chars,每个字母只能用一次,所以用大小为26的数组charsArray来表示a-z(例如charsArra ...
- JavaScript数字精度丢失的一些问题
本文分为三个部分 JS 数字精度丢失的一些典型问题 JS 数字精度丢失的原因 解决方案(一个对象+一个函数) 一.JS数字精度丢失的一些典型问题 1. 两个简单的浮点数相加 1 0.1 + 0.2 ! ...
- main方法的详解
格式 * public static void main(String[] args) {} 针对格式的解释 public 被jvm调用,访问权限足够大. static 被jvm调用,不用创建对象,直 ...
- [Java复习] 分布式PRC - Dubbo
分布式RPC框架 dubbo常见问题: 1. 问dubbo的工作原理:服务注册,注册中心,服务生产者,消费者,代理通信,负载均衡 2. 问网络通信,序列化: dubbo协议,长连接,NIO,hessi ...
- Linux系列之——tomcat 的开机自启动
--未验证 每次开机都要启动tomcat,非常麻烦:通过直接修改系统文件,实现tomcat自启动: 1. 修改脚本文件rc.local:vim /etc/rc.d/rc.local 这个脚本是使用者自 ...
- osg qt fbx ifc bim osg ive 3ds max rvt
项目环境变量配置 include E:\Qt\Qt5.12.2\5.12.2\msvc2017_64\include E:\OpenSourceGraph\OpenSceneGraph_install ...
- Chrome浏览器控制网速的方法