添加StockController方法:
1. @GetMapping("test/read") 2. public String testRead(){ 3. String msg = stockService.testRead(); 4. return "测试读"; 5. } 6. @GetMapping("test/write") 7. public String testWrite(){ 8. String msg = stockService.testWrite(); 9. return "测试写"; 10. }
添加StockService方法:
1. public String testRead() { 2. RReadWriteLock rwLock = this.redissonClient.getReadWriteLock("rwLock"); 3. rwLock.readLock().lock(10, TimeUnit.SECONDS); 4. System.out.println("测试读锁。。。。"); 5. // rwLock.readLock().unlock(); 6. return null; 7. } 8. public String testWrite() { 9. RReadWriteLock rwLock = this.redissonClient.getReadWriteLock("rwLock"); 10. rwLock.writeLock().lock(10, TimeUnit.SECONDS); 11. System.out.println("测试写锁。。。。"); 12. // rwLock.writeLock().unlock(); 13. return null; 14. }
打开开两个浏览器窗口测试:
- 同时访问写:一个写完之后,等待一会儿(约10s),另一个写开始
- 同时访问读:不用等待
- 先写后读:读要等待(约10s)写完成
- 先读后写:写要等待(约10s)读完成
信号量(Semaphore)
基于Redis的Redisson的分布式信号量(Semaphore)Java对象 RSemaphore 采用了与
java.util.concurrent.Semaphore 相似的接口和用法。同时还提供了异步(Async)、反射式
(Reactive)和RxJava2标准的接口。
1. RSemaphore semaphore = redisson.getSemaphore("semaphore"); 2. semaphore.acquire(); 3. semaphore.release();
在StockController添加方法:
1. @GetMapping("test/semaphore") 2. public String testSemaphore(){ 3. this.stockService.testSemaphore(); 4. return "测试信号量"; 5. }
在StockService添加方法:
1. public void testSemaphore() { 2. RSemaphore semaphore = this.redissonClient.getSemaphore("semaphore"); 3. semaphore.trySetPermits(3); 4. try { 5. semaphore.acquire(); 6. TimeUnit.SECONDS.sleep(5); 7. System.out.println(System.currentTimeMillis()); 8. semaphore.release(); 9. } catch (InterruptedException e) { 10. e.printStackTrace(); 11. } 12. }
添加测试用例:并发10次,循环一次
控制台效果:
由此可知:
- 1606960790秒有3次请求进来:每个控制台各1次
- 1606960795秒有3次请求进来:控制台2有1次,控制台3有2次
- 1606960800秒有3次请求进来:控制台1有2次,控制台2有1次
- 1606960805秒有1次请求进来:控制台1有1次
闭锁(CountDownLatch)
基于Redisson的Redisson分布式闭锁(CountDownLatch)Java对象 RCountDownLatch 采用了与
java.util.concurrent.CountDownLatch 相似的接口和用法。
1. RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch"); 2. latch.trySetCount(1); 3. latch.await(); 4. // 在其他线程或其他JVM里 5. RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch"); 6. latch.countDown();
需要两个方法:一个等待,一个计数countDown
给StockController添加测试方法
1. @GetMapping("test/latch") 2. public String testLatch(){ 3. this.stockService.testLatch(); 4. return "班长锁门。。。"; 5. } 6. @GetMapping("test/countdown") 7. public String testCountDown(){ 8. this.stockService.testCountDown(); 9. return "出来了一位同学"; 10. }
给StockService添加测试方法
1. public void testLatch() { 2. RCountDownLatch latch = this.redissonClient.getCountDownLatch("latch"); 3. latch.trySetCount(6); 4. try { 5. latch.await(); 6. } catch (InterruptedException e) { 7. e.printStackTrace(); 8. } 9. } 10. 11. public void testCountDown() { 12. RCountDownLatch latch = this.redissonClient.getCountDownLatch("latch"); 13. latch.trySetCount(6); 14. latch.countDown(); 15. }
重启测试,打开两个页面:当第二个请求执行6次之后,第一个请求才会执行。
总结
redisson:redis的java客户端,分布式锁
玩法:
1.引入依赖
2.java配置类:RedissonConfig
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.useSingleServer().setAddress("redis://ip:port");
return Redisson.create(config);
}
3.代码使用:
可重入锁RLock对象:CompletableFuture + lua脚本 + hash
RLock lock = this.redissonClient.getLock("xxx");
lock.lock()/unlock()
公平锁:
RLock lock = this.redissonClient.getFairLock("xxx");
lock.lock()/unlock()
联锁 和 红锁:
读写锁:
RReadWriteLock rwLock = this.redissonClient.getReadWriteLock("xxx");
rwLock.readLock().lock()/unlock();
rwLock.writeLock().lock()/unlock();
信号量:
RSemaphore semaphore = this.redissonClient.getSemaphore("xxx");
semaphore.trySetPermits(3);
semaphore.acquire()/release();
闭锁:
RCountDownLatch cdl = this.redissonClient.getCountDownLatch("xxx");
cdl.trySetCount(6);
cdl.await()/countDowntch();