Java中String做为synchronized同步锁
? synchronized (("" + userId).intern()) { // TODO:something } ? JVM内存区域里面有一块常量池,关于常量池的分配:
字符串是存储在常量池中的,有两种类型的字符串数据会存储在常量池中:
常量池中的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); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |