当前位置: 首页 > news >正文

公司无网站无平台怎么做外贸新闻网站排行榜

公司无网站无平台怎么做外贸,新闻网站排行榜,免费的破解版wordpress主题,网站备案信息真实性核验单 下载需求: 操作员能够对自己权限下的用户数据进行数据填充,但是不同操作员之间可能会有重复的用户数据,为了避免操作员覆盖数据或者重复操作数据,应该在操作用户数据时加锁,要求加的这一把锁必须是细粒度的锁,…

需求:

操作员能够对自己权限下的用户数据进行数据填充,但是不同操作员之间可能会有重复的用户数据,为了避免操作员覆盖数据或者重复操作数据,应该在操作用户数据时加锁,要求加的这一把锁必须是细粒度的锁,不能锁住所有用户的操作 ,只锁当前操作用户,锁的名字为用户id,在获取到锁之后执行业务操作,否则阻塞等待, 这个单体服务锁工具如何设计?

思路:

思路:

  • 1、锁工具类:首先创建一个ConcurrentHashMap{k(用户id)
    v(锁实例)},包含获取锁方法,定时任务晚上删除map中键值对的方法(尝试获取锁,如果能够拿到锁就说明锁没有在使用)
  • 2、在定时任务删除某个键值对期间,去尝试获取写锁,如果能够获取到说明所以经不再被使用,直接删除map中的键值对,之后被删除的锁实例失效
  • 3、其他线如果在删除锁实例之前获取到了,在执行业务的前后需要判断一下这把锁是否和当前key下的锁实例是否一致,一样执行业务,否则锁失效,抛异常,事务回滚

代码:

public class LockUtilsTest {public   static final ConcurrentHashMap<String, ReentrantLock> lockMap = new ConcurrentHashMap<>();private static  ScheduledExecutorService scheduledExecutorService;private static volatile boolean scheduledTaskCreated = false;/*** 获取锁实例,如果锁不存在就创建一个新的锁实例,并将这个锁实例返回* @param lockName* @return*/public static final ReentrantLock getLock(String lockName) {return lockMap.computeIfAbsent(lockName, key -> {//创建定时任务createdTask();return  new ReentrantLock();});}/**** 懒加载 创建定时任务*/private static void createdTask(){System.out.println(Thread.currentThread().getName()+":尝试创建定时任务");if (!scheduledTaskCreated) {synchronized (LockUtilsTest.class) {if (!scheduledTaskCreated) {System.out.println(Thread.currentThread().getName()+":成功创建定时任务");scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();scheduledExecutorService.scheduleAtFixedRate(() -> {// 调用当前类的 clearUserLocks 方法new LockUtilsTest().clearUserLocks();}, 3, 3, TimeUnit.SECONDS);scheduledTaskCreated = true;}else{System.out.println(Thread.currentThread().getName()+":尝试创建定时任务发现定时任务已经被创建");}}}else{System.out.println(Thread.currentThread().getName()+":尝试创建定时任务发现定时任务已经被创建");}}/*** 遍历map,尝试获取锁,没获取到说明这个key的锁还在被使用,获取到就直接删除这个键值对,并且其他拥有这个被删除的锁实例的线程获取到锁也不执行业务*/private  void clearUserLocks() {if (StringUtils.isNotEmpty(lockMap) && lockMap.size() >0){System.out.println(Thread.currentThread().getName()+":执行定时任务,删除未使用的锁");ArrayList<String> keys = new ArrayList<>();lockMap.forEach((key, value) -> {ReentrantLock lock = lockMap.get(key);//获取到锁之后直接删除键值对,否则锁在被使用不删除if (lock.tryLock()){try {keys.add(key);lockMap.remove(key);}finally {lock.unlock();lock = null;//取消强引用防止内存泄露}}});System.out.println(Thread.currentThread().getName()+":被删除的锁:"+keys.toString());}}/*** 极端情况下才会考虑这种删除锁时,可以使用分段锁思想,加入一百万个用户,我按照一个用户一把锁,估计会创建一百万把,但是使用分段锁之后,可以让一万个用户公用一把锁,* 这样就会减少锁的数量,还有频繁加锁和释放锁带来的开销,相比与百万数据公用一把锁改成万人用一把锁,性能是有明显提升的,锁的垃圾回收也要处理好,不要出现内存泄露*//**** 判断锁是否有效 :当定时任务删除对应键的锁时,如果有线程已经获得这个键原来的锁实例没抢到锁时,恰好另一个线程在清空键值对后获取这个key的锁实例,这个key在这一瞬间就会存在两个锁实例* 他们可以同时执行业务,彼此并不互斥,所以当获得锁之后,要再次和当前锁是否一致,只要不一致就说明这个锁实例不能再使用了,会存在线程不安全问题* @param lockName*/public static final Boolean checkLock(String lockName,ReentrantLock checkLock){ReentrantLock nowLock = lockMap.get(lockName);/**确保锁存在并且  比较两个对象是否是一个实例*/if (ObjectUtil.isNotEmpty(nowLock) && checkLock == nowLock){return true;}return false;}//使用这个方法如果有数据库操作,要加事务注解回滚数据public static final void checkLockFlag(String lockName,ReentrantLock checkLock){ReentrantLock nowLock = lockMap.get(lockName);/**确保锁存在并且  比较两个对象是否是一个实例*/if (ObjectUtil.isNotEmpty(nowLock) && checkLock == nowLock){}else{throw new RuntimeException("当前锁已失效");}}
}class LockUtilsTestClass{public static void main(String[] args) {//测试定时任务是否是单例懒加载创建   =》 目标 : 成功创建定时任务//taskTest();//测试一百个线程抢锁,锁阻塞是否生效 =》 目标 :执行业务出现一百次  后缀是同一把锁//lockTest();//测试锁被删除后,已经获取锁实例的线程是否生效  =》 目标:老锁返回友好提示 五次  √delLockTest();}/*** 测试定时任务是否是单例懒加载创建* 预期结果:* 尝试创建定时任务  100次* 尝试创建定时任务发现定时任务已经被创建  99次* 成功创建定时任务  1次*/static void   taskTest(){for (int i = 0; i < 100; i++) {new Thread(() ->{ReentrantLock testLock = LockUtilsTest.getLock("test");}).start();}}/**** 测试锁阻塞是否生效 =》 目标 同一个锁执行业务一百次*/static  void lockTest(){for (int i = 0; i < 100; i++) {new Thread(() ->{String lockName = "fe2r32r23f34t34tf34f34fd";ReentrantLock lock = LockUtilsTest.getLock(lockName);lock.lock();try {System.out.println("执行业务"+lock.toString());}finally {lock.unlock();}}).start();}}static   void delLockTest(){for (int i = 0; i < 5; i++) {new Thread(() ->{String lockName = "fe2r32r23f34t34tf34f34fd";ReentrantLock lock = LockUtilsTest.getLock(lockName);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}lock.lock();try {if (LockUtilsTest.checkLock(lockName,lock)){//执行业务System.out.println("老锁执行业务");}else{//当前线程持有锁失效,返回友好提示System.out.println("老锁返回友好提示");}}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}}).start();}}
}

工具类优缺点:

  • 使用ConcurrentHashMap作为锁的存储容器有以下优点

  • 线程安全:ConcurrentHashMap本身是线程安全的,多个线程可以并发地访问和修改它,而无需额外的同步。

  • 高效性:ConcurrentHashMap在并发场景下通常比synchronizedMap或Hashtable等同步容器有更好的性能。

  • 灵活性:你可以根据键(例如资源的唯一标识)动态地获取和释放锁,这使得代码更加灵活和可维护。

  • 重用锁对象:尽可能地重用现有的锁对象,而不是为每个新的资源或操作都创建一个新的锁,如果你频繁地创建和销毁锁对象,或者维护大量的锁对象(如存储在ConcurrentHashMap中),那么这确实会增加内存消耗。每个ReentrantLock对象都会占用一定的内存空间,而且如果锁的数量非常大,那么存储这些锁的数据结构(如ConcurrentHashMap)也会占用更多的内存,当你动态地获取锁时,JVM会确保线程安全地访问锁对象,这通常涉及一些底层的同步机制,但这些机制通常不会引入大量的额外内存消耗。同样,释放锁也只是改变锁的状态,使其可以被其他线程获取,这同样是一个轻量级的操作。

  • 注意问题

  • 避免无限制地增长:虽然将锁存储在ConcurrentHashMap中可以限制锁对象的数量,但如果你的应用程序允许无限制地添加新的键(即资源),那么lockMap本身可能会无限制地增长,从而消耗大量内存。确保你的应用程序有适当的机制来管理资源,避免无限制地添加新的锁。

http://www.yidumall.com/news/51460.html

相关文章:

  • 网站开发人员分配广州商务网站建设
  • 天元建设集团有限公司证券北京网站优化效果
  • 做网站销售这几天你有什么想法企业网站建设
  • ASP动态网站制作外贸推广优化公司
  • 安阳市文峰区疫情最新消息seo推广技术培训
  • 有好点的做网站的公司吗百度百科官网登录
  • 金诚财富网站是谁做的推广文案怎么写
  • 制作网页创建站点的步骤俄罗斯搜索引擎入口 yandex
  • 日本可以自己做网站吗?sem培训班学费哪个好
  • jsp做简单校园网站推广软件
  • 虚拟空间怎么做网站目录指向二级子域名ip地址查询
  • 汽车网站建设公司哪家好一个万能的营销方案
  • oa办公软件手机版抖音seo点击软件排名
  • 建筑网站知乎seo站长查询
  • 建设局网站首页友情链接有哪些展现形式
  • 手机制作网站软件市场调研的基本流程
  • 台海最新24小时消息vue seo优化
  • 做母婴产品哪个网站做的好谷歌seo新规则
  • 传奇世界页游北京seo运营推广
  • 哔哩哔哩网站电子商务建设郑州网站制作工具
  • 吴桥县做网站日本免费服务器ip地址
  • 浙江做电缆桥架的公司网站长沙seo运营
  • 个人做网站郊游的英网络营销师证书含金量
  • 做画册找什么网站win优化大师有免费版吗
  • 企业工商信息查询平台邯郸网站建设优化
  • 馆陶企业做网站推广搜狗推广登陆
  • 网站建设 inurl:.bbs线上营销渠道有哪些
  • 可以做调查的网站网站的网络推广
  • php网站备份传播易广告投放平台
  • 普通电脑怎么做网站服务器吗google官网入口下载