1、问题发现
虽说,synchronized 关键字万能的,在并发上去之后,这个插入就显得很慢了。仔细观察发现,其实锁的粒度还是再细点,可以根据AlarmRules对象的ID来锁。
2、解决过程
很明显synchronized(rules) 这个写法是有问题的。是基于对象的引用作为锁,只有在rules实例相同的情况下。我们实际情况实例不同,id相同的情况。
查询相关资料。进行相关测试 采用
ConcurrentHashMap(线程安全map) + ReentrantLock(可重入的锁)
public class MainTest {public static void main(String[] args) {for (int i = 1; i < 20; i++) {AlarmRules temp = new AlarmRules();temp.setId(i % 4);new Thread(new Test(temp)).start();}System.out.println("for end");}
}
Runnable
public class Test implements Runnable {private AlarmRules bean;public Test(AlarmRules bean){this.bean = bean;}@Overridepublic void run() {SynchTest.synchMethod(bean);}
}
method
public class SynchTest {private static final Map<Integer, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>();public static void synchMethod(AlarmRules bean){ReentrantLock lock = LOCK_MAP.computeIfAbsent(bean.getId(), k -> new ReentrantLock());lock.lock();try {System.out.println("bean.getId() = " + bean.getId()+" bean selectOne");Thread.sleep(2000);System.out.println("bean.getId() = " + bean.getId()+" bean insert");Thread.sleep(1000);}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}}
}
效果实现。id不同的完美并发执行。提高了方法的效率。
注意
因我有用 CountDownLatch,在latch.await(); 清理资源
LOCK_MAP.remove(rules.getId()); 避免OOM