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

监控视频做直播网站网站建设费摊销期限

监控视频做直播网站,网站建设费摊销期限,搭建网站是什么专业,淘宝seo软件需求: 操作员能够对自己权限下的用户数据进行数据填充,但是不同操作员之间可能会有重复的用户数据,为了避免操作员覆盖数据或者重复操作数据,应该在操作用户数据时加锁,要求加的这一把锁必须是细粒度的锁,…

需求:

操作员能够对自己权限下的用户数据进行数据填充,但是不同操作员之间可能会有重复的用户数据,为了避免操作员覆盖数据或者重复操作数据,应该在操作用户数据时加锁,要求加的这一把锁必须是细粒度的锁,不能锁住所有用户的操作 ,只锁当前操作用户,锁的名字为用户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.yayakq.cn/news/39948/

相关文章:

  • 厦门律师网站建设wordpress对配置的要求
  • 网站图片上传却不显示区块链app开发价格
  • 做网站vi系统是什么wordpress 管理登录
  • 塔城建设局网站西安房价走势最新消息
  • 爬虫代理ip购买如何做网站排名优化
  • 企业网站访问对象有哪些免费网络软件
  • 外贸网站怎么做才好足球直播网站开发定制
  • 合肥做网站的软件公司网络营销常用的工具有哪些
  • 做seo哪些网站会好点自己免费制作logo软件
  • 深色大气网站模板wordpress手机站如何做
  • 没有有知道钓鱼网站在哪儿做秒收录的网站
  • 网站页脚模板专做淘宝的网站
  • 郑州seo网站管理网站开发是否交印花税
  • 少主网络建站公司网站建设开发维护工作总结
  • 品牌网站怎么做南联网站建设哪家好
  • 网站全局参数设置临沂网站建设和轶件安装
  • 呼伦贝尔市建设网站在线做编程题的网站
  • 蚌埠网站优化昆山汽车网站建设
  • 建站网站图片不显示企业服务公司经营范围
  • 郑州网站建设代理godaddy如何创建网站
  • 惠州营销网站制作静态网站后台
  • 网站建设代理加盟内蒙古有做购物网站的吗
  • 引蜘蛛网站建设高校图书馆网站的意义
  • 做直播网站要多大带宽3d建模师工资一般多少
  • 网站建设教程费用北京新机场建设网站
  • 工业和信息化部网站备案近期时事新闻
  • 做问卷调查的是哪个网站好昌吉做网站推广的公司
  • 网站模板怎么设计软件做外贸产品上什么网站
  • 手机网站建站工作室百度人工服务
  • 怎么做网站推广知乎网站开发好的公司推荐