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

flask 简易网站开发中山高端网站建设

flask 简易网站开发,中山高端网站建设,上海公司注册网上查名,海口企业网站建设前两个版本的代码 都或多或少存在一定的问题#xff0c;虽然可能微乎其微#xff0c;但是程序需要严谨再严谨#xff0c; 第一个版本问题#xff1a; 局限于单机版#xff0c;依赖于 Jvm的锁 第二个版本问题#xff1a; 极端情况下#xff0c;解锁逻辑的问题#xf…前两个版本的代码 都或多或少存在一定的问题虽然可能微乎其微但是程序需要严谨再严谨 第一个版本问题 局限于单机版依赖于 Jvm的锁 第二个版本问题 极端情况下解锁逻辑的问题线程B的锁可能会被线程A解掉这种情况实际上是不合理的。 1. 由于是客户端自己生成过期时间所以需要强制要求分布式下每个客户端的时间必须同步。 2. 当锁过期的时候如果多个客户端同时执行jedis.getSet()方法那么虽然最终只有一个客户端可以加锁 但是这个客户端的锁的过期时间可能被其他客户端覆盖。 3. 锁不具备拥有者标识即任何客户端都可以解锁。 版本一 http://www.cnblogs.com/xifenglou/p/8807323.html 版本二 http://www.cnblogs.com/xifenglou/p/8883717.html所以基于以上问题第三个版本出来了 Talk is cheap, show me the code!import org.springframework.util.StopWatch; import redis.clients.jedis.Jedis;import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;/*** 使用RedisTool.tryGetDistributedLock* 实现 分布式锁* 终极版本*/ public class TicketRunnable3 implements Runnable {private CountDownLatch count;private CyclicBarrier barrier;private static final Integer Lock_Timeout 10000;private static final String lockKey LockKey;private volatile static boolean working true;public TicketRunnable3(CountDownLatch count, CyclicBarrier barrier) {this.count count;this.barrier barrier;}private int num 20; // 总票数 此处可随意 写一个数保证线程能运行起来真正的共享变量不应该写死在程序中 应该从redis中获取这样模拟多进程多线程的并发访问public void sellTicket(Jedis jedis) {String name Thread.currentThread().getName();try{boolean getLock RedisTool.tryGetDistributedLock(jedis,lockKey, name,Lock_Timeout);if( getLock){if(!working)return;// Do your jobnum Integer.parseInt(jedis.get(ticket));if (num 0) {num--;jedis.set(ticket,num);if(num!0)System.out.println(Thread.currentThread().getName() 售出票号 (num1),还剩 num 张票-- );else {System.out.println(Thread.currentThread().getName() 售出票号 (num1)票已经票完!--);working false;}}}else{//System.out.println();if(!working)return;System.out.println(Thread.currentThread().getName() Try to get the Lock,and wait 20 millisecond....);Thread.sleep(10);}}catch(Exception e){System.out.println(e);}finally {try {if(RedisTool.releaseDistributedLock(jedis,lockKey,name)){Thread.sleep(30);}}catch (Exception e ) {e.printStackTrace();}}}Overridepublic void run() {System.out.println(Thread.currentThread().getName()到达,等待中...);Jedis jedis new Jedis(localhost, 6379);try{barrier.await(); // 此处阻塞 等所有线程都到位后 一起进行抢票if(Thread.currentThread().getName().equals(pool-1-thread-1)){System.out.println(-----------------全部线程准备就绪,开始抢票------------------);}else {Thread.sleep(5);}while (working) {sellTicket(jedis);}count.countDown(); //当前线程结束后计数器-1}catch (Exception e){e.printStackTrace();}}/**** param args*/public static void main(String[] args) {int threadNum 5; //模拟多个窗口 进行售票final CyclicBarrier barrier new CyclicBarrier(threadNum);final CountDownLatch count new CountDownLatch(threadNum); // 用于统计 执行时长StopWatch watch new StopWatch();watch.start();TicketRunnable3 tickets new TicketRunnable3(count,barrier);ExecutorService executorService Executors.newFixedThreadPool(threadNum);//ExecutorService executorService Executors.newCachedThreadPool();for (int i 0; i threadNum; i) { //此处 设置数值 受限于 线程池中的数量executorService.submit(tickets);}try {count.await();executorService.shutdown();watch.stop();System.out.println(耗 时: watch.getTotalTimeSeconds() 秒);} catch (InterruptedException e) {e.printStackTrace();}} } import redis.clients.jedis.Jedis; import java.util.Collections;public class RedisTool {private static final String LOCK_SUCCESS OK;private static final String SET_IF_NOT_EXIST NX;private static final String SET_WITH_EXPIRE_TIME PX;private static final Long RELEASE_SUCCESS 1L;/** * 尝试获取分布式锁* param jedis Redis客户端* param lockKey 锁* param requestId 请求标识* param expireTime 超期时间* return 是否获取成功*/public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {String result jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);if (LOCK_SUCCESS.equals(result)) {System.out.println(Thread.currentThread().getName() 获取到锁,开始工作);return true;}return false;}/*** 释放分布式锁* param jedis Redis客户端* param lockKey 锁* param requestId 请求标识* return 是否释放成功*/public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {String script if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end;Object result jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));if (RELEASE_SUCCESS.equals(result)) {System.out.println(Thread.currentThread().getName() 解锁成功);return true;}return false;}} 解锁部分我们将Lua代码传到jedis.eval()方法里并使参数KEYS[1]赋值为lockKeyARGV[1]赋值为requestId。eval()方法是将Lua代码交给Redis服务端执行。 那么这段Lua代码的功能是什么呢其实很简单首先获取锁对应的value值检查是否与requestId相等如果相等则删除锁解锁。那么为什么要使用Lua语言来实现呢因为要确保上述操作是原子性的。源于Redis的特性下面是官网对eval命令的部分解释 简单来说就是在eval命令执行Lua代码的时候Lua代码将被当成一个命令去执行并且直到eval命令执行完成Redis才会执行其他命令。 运行结果如下 欢迎留言期待更深层次的探讨 针对 上述代码使用两个类 运行 TicketRunnable3  TicketRunnable4 模拟多进程  多线程场景 场景1 运行时长  过期时长     此时 锁自动失效 线程均不用解锁即使解锁也是失败 代码及运行结果如下 import org.springframework.util.StopWatch; import redis.clients.jedis.Jedis;import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;/*** 使用RedisTool.tryGetDistributedLock* 实现 分布式锁* 终极版本*/ public class TicketRunnable4 implements Runnable {private CountDownLatch count;private CyclicBarrier barrier;private static final Integer Lock_Timeout 3000; // 过期时间 代表 3秒后过期private static final Integer ExecuteTime 5000;private static final Integer RetryInterval 20;private static final String lockKey LockKey;private volatile static boolean working true;public TicketRunnable4(CountDownLatch count, CyclicBarrier barrier) {this.count count;this.barrier barrier;}private int num 20; // 总票数public void sellTicket(Jedis jedis) {String name Thread.currentThread().getName();boolean gotLock false;try{gotLock RedisTool.tryGetDistributedLock(jedis,lockKey, name,Lock_Timeout);if( gotLock working){// Do your jobnum Integer.parseInt(jedis.get(ticket));if (num 0) {num--;jedis.set(ticket,num);if(num!0)System.out.println(name 售出票号 (num1),还剩 num 张票-- );else {System.out.println(name 售出票号 (num1)票已经票完!--);return;}}if(num 0){System.out.println(name票已经被抢空啦);working false;}Thread.sleep(ExecuteTime);}else{//System.out.println();//System.out.println(name Try to get the Lock,and wait RetryInterval millisecond....);Thread.sleep(RetryInterval);}}catch(Exception e){System.out.println(e);}finally {try {if(!gotLock||!working) //未获取到锁的线程不用解锁return;/*** 解锁成功后 sleep, 尝试让出cpu给其他线程机会* 解锁失败 说明锁已经失效 被其他线程获取到*/if(RedisTool.releaseDistributedLock(jedis,lockKey,name)){Thread.sleep(100);}}catch (Exception e ) {e.printStackTrace();}}}Overridepublic void run() {String prefix #;String threadName Thread.currentThread().getName();Thread.currentThread().setName(prefixthreadName);System.out.println(Thread.currentThread().getName()到达,等待中...);Jedis jedis new Jedis(localhost, 6379);try{barrier.await(); // 此处阻塞 等所有线程都到位后 一起进行抢票if(Thread.currentThread().getName().equals(prefixpool-1-thread-2)){System.out.println(-----------------全部线程准备就绪,开始抢票------------------);}else {Thread.sleep(5);}while (working) {sellTicket(jedis);}count.countDown(); //当前线程结束后计数器-1}catch (Exception e){e.printStackTrace();}}/**** param args*/public static void main(String[] args) {int threadNum 3; //模拟多个窗口 进行售票final CyclicBarrier barrier new CyclicBarrier(threadNum);final CountDownLatch count new CountDownLatch(threadNum); // 用于统计 执行时长StopWatch watch new StopWatch();watch.start();TicketRunnable4 tickets new TicketRunnable4(count,barrier);ExecutorService executorService Executors.newFixedThreadPool(threadNum);//ExecutorService executorService Executors.newCachedThreadPool();for (int i 0; i threadNum; i) { //此处 设置数值 受限于 线程池中的数量executorService.submit(tickets);}try {count.await();executorService.shutdown();watch.stop();System.out.println(耗 时: watch.getTotalTimeSeconds() 秒);} catch (InterruptedException e) {e.printStackTrace();}} } TicketRunnable3 售出 10 9 8 6 5 3 2 1 票号。 TicketRunnable4售出  7 4  两个票号 合计10张票模拟结束 场景2 运行时长 过期时长     此时 此时需要有锁线程去释放锁这样多线程再去竞争获取锁。 修改代码 private static final Integer Lock_Timeout 5000; // 将时间从3秒改为5秒 private static final Integer ExecuteTime 3000; // 将执行时间5秒改为3秒运行结果如下 一个进程售出 10 9 8 6 4 3 1 票号 另一进程售出 7 5 2 票号 此时 每个线程完成任务后均需要释放锁这样本地线程或是异地线程 才能获取到锁这样才能有机会进行任务的执行
http://www.pierceye.com/news/377742/

相关文章:

  • 根据颜色找网站济南做网站公司排名
  • 面对面视频 网站开发网络科技加我qq是干嘛
  • 如何登录网站制作平台百度旧版本
  • 广东营销型网站建设报价定制商品的app
  • 网站导航常用关键字电子商务网站设计内容
  • 建设vip网站相关视频wordpress 修改用户头像
  • 考百度指数 某个关键词在某个行业网站上的wordpress与Wix对比
  • 机器人网站建设规划书福州网站制作怎样
  • 自己创建一个网站需要多少钱2023最建议买10款手机
  • 寻找富阳网站建设国内个人网站欣赏
  • 企业自建站城市建设模拟游戏官方网站
  • 网站建设数据库类型建立网站信息发布登记制度
  • it培训机构都有哪些seo推广教程seo推广技巧
  • 龙岩网站开发较好的公司wordpress屏蔽首页
  • 有没有做美食的网站深圳网站建站公司
  • 学校网站建设需求分析调研表网站右侧信息跟随左侧菜单栏变化
  • 家乡网站建设策划案邢台哪里建网站
  • 网站建设实习收获青岛网上房地产网站
  • 简述电子政务网站设计的技术企业邮箱是什么类型的账户
  • 深圳网站建设公司元嘉定网站开发
  • 佛山外贸网站建设平台上传网站安装教程
  • c2c网站建设实例德国网站建设
  • 建网站支持设备是什么意思佛山中小企业网站建设
  • 网站建设与管理读后感宁德住房和城乡建设部网站
  • 贸易网站建站建设部网站社保联网
  • 住房城乡建设厅网站准考证如何建小企业网站
  • 葫芦岛市城乡建设局网站做什么样的网站
  • 铜山区规划建设局网站大学生心理咨询网站建设论文
  • 泸州本地网站建设扬州做网站公司
  • 镇江网站建设工作室怎么购买国外的域名