mirror of
https://gitee.com/52itstyle/spring-boot-seckill.git
synced 2026-05-13 02:42:29 +00:00
码友<马丁的早晨>的建议 使用AOP + 锁实现
This commit is contained in:
40
src/main/java/com/itstyle/seckill/common/aop/LockAspect.java
Normal file
40
src/main/java/com/itstyle/seckill/common/aop/LockAspect.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package com.itstyle.seckill.common.aop;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
/**
|
||||
* 同步锁 AOP
|
||||
* 创建者 张志朋
|
||||
* 创建时间 2015年6月3日
|
||||
*/
|
||||
@Component
|
||||
@Scope
|
||||
@Aspect
|
||||
public class LockAspect {
|
||||
/**
|
||||
* 思考:为什么不用synchronized
|
||||
* service 默认是单例的,并发下lock只有一个实例
|
||||
*/
|
||||
private static Lock lock = new ReentrantLock(true);//互斥锁 参数默认false,不公平锁
|
||||
|
||||
//Service层切点 用于记录错误日志
|
||||
@Pointcut("@annotation(com.itstyle.seckill.common.aop.Servicelock)")
|
||||
public void lockAspect() {
|
||||
|
||||
}
|
||||
|
||||
@Around("lockAspect()")
|
||||
public Object doAfterThrowing(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
lock.lock();
|
||||
Object obj= joinPoint.proceed();
|
||||
lock.unlock();
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.itstyle.seckill.common.aop;
|
||||
import java.lang.annotation.*;
|
||||
/**
|
||||
* 自定义注解 同步锁
|
||||
* 创建者 张志朋
|
||||
* 创建时间 2015年6月3日
|
||||
*/
|
||||
@Target({ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Servicelock {
|
||||
String description() default "";
|
||||
}
|
||||
@@ -47,6 +47,13 @@ public interface ISeckillService {
|
||||
* @return
|
||||
*/
|
||||
Result startSeckilLock(long seckillId,long userId);
|
||||
/**
|
||||
* 秒杀 二、程序锁AOP
|
||||
* @param seckillId
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
Result startSeckilAopLock(long seckillId,long userId);
|
||||
|
||||
/**
|
||||
* 秒杀 二、数据库悲观锁
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.itstyle.seckill.common.aop.Servicelock;
|
||||
import com.itstyle.seckill.common.dynamicquery.DynamicQuery;
|
||||
import com.itstyle.seckill.common.entity.Result;
|
||||
import com.itstyle.seckill.common.entity.Seckill;
|
||||
@@ -110,6 +111,28 @@ public class SeckillServiceImpl implements ISeckillService {
|
||||
return Result.ok(SeckillStatEnum.SUCCESS);
|
||||
}
|
||||
@Override
|
||||
@Servicelock
|
||||
@Transactional
|
||||
public Result startSeckilAopLock(long seckillId, long userId) {
|
||||
//来自码云码友<马丁的早晨>的建议 使用AOP + 锁实现
|
||||
String nativeSql = "SELECT number FROM seckill WHERE seckill_id=?";
|
||||
Object object = dynamicQuery.nativeQueryObject(nativeSql, new Object[]{seckillId});
|
||||
Long number = ((Number) object).longValue();
|
||||
if(number>0){
|
||||
nativeSql = "UPDATE seckill SET number=number-1 WHERE seckill_id=?";
|
||||
dynamicQuery.nativeExecuteUpdate(nativeSql, new Object[]{seckillId});
|
||||
SuccessKilled killed = new SuccessKilled();
|
||||
killed.setSeckillId(seckillId);
|
||||
killed.setUserId(userId);
|
||||
killed.setState(Short.parseShort(number+""));
|
||||
killed.setCreateTime(new Timestamp(new Date().getTime()));
|
||||
dynamicQuery.save(killed);
|
||||
}else{
|
||||
return Result.error(SeckillStatEnum.END);
|
||||
}
|
||||
return Result.ok(SeckillStatEnum.SUCCESS);
|
||||
}
|
||||
@Override
|
||||
@Transactional
|
||||
public Result startSeckilDBPCC_ONE(long seckillId, long userId) {
|
||||
//单用户抢购一件商品或者多件都没有问题
|
||||
@@ -173,4 +196,5 @@ public class SeckillServiceImpl implements ISeckillService {
|
||||
return Result.error(SeckillStatEnum.END);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -84,12 +84,38 @@ public class SeckillController {
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
@ApiOperation(value="秒杀三(数据库悲观锁)",nickname="科帮网")
|
||||
@ApiOperation(value="秒杀三(AOP程序锁)",nickname="科帮网")
|
||||
@PostMapping("/startLock")
|
||||
public Result startAopLock(long seckillId){
|
||||
seckillService.deleteSeckill(seckillId);
|
||||
final long killId = seckillId;
|
||||
LOGGER.info("开始秒杀三(正常)");
|
||||
for(int i=0;i<1000;i++){
|
||||
final long userId = i;
|
||||
Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Result result = seckillService.startSeckilLock(killId, userId);
|
||||
LOGGER.info("用户:{}{}",userId,result.get("msg"));
|
||||
}
|
||||
};
|
||||
executor.execute(task);
|
||||
}
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
Long seckillCount = seckillService.getSeckillCount(seckillId);
|
||||
LOGGER.info("一共秒杀出{}件商品",seckillCount);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
@ApiOperation(value="秒杀四(数据库悲观锁)",nickname="科帮网")
|
||||
@PostMapping("/startDBPCC_ONE")
|
||||
public Result startDBPCC_ONE(long seckillId){
|
||||
seckillService.deleteSeckill(seckillId);
|
||||
final long killId = seckillId;
|
||||
LOGGER.info("开始秒杀三(正常)");
|
||||
LOGGER.info("开始秒杀四(正常)");
|
||||
for(int i=0;i<1000;i++){
|
||||
final long userId = i;
|
||||
Runnable task = new Runnable() {
|
||||
@@ -110,12 +136,12 @@ public class SeckillController {
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
@ApiOperation(value="秒杀四(数据库悲观锁)",nickname="科帮网")
|
||||
@ApiOperation(value="秒杀五(数据库悲观锁)",nickname="科帮网")
|
||||
@PostMapping("/startDPCC_TWO")
|
||||
public Result startDPCC_TWO(long seckillId){
|
||||
seckillService.deleteSeckill(seckillId);
|
||||
final long killId = seckillId;
|
||||
LOGGER.info("开始秒杀四(正常、数据库锁最优实现)");
|
||||
LOGGER.info("开始秒杀五(正常、数据库锁最优实现)");
|
||||
for(int i=0;i<1000;i++){
|
||||
final long userId = i;
|
||||
Runnable task = new Runnable() {
|
||||
@@ -136,12 +162,12 @@ public class SeckillController {
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
@ApiOperation(value="秒杀五(数据库乐观锁)",nickname="科帮网")
|
||||
@ApiOperation(value="秒杀六(数据库乐观锁)",nickname="科帮网")
|
||||
@PostMapping("/startDBOCC")
|
||||
public Result startDBOCC(long seckillId){
|
||||
seckillService.deleteSeckill(seckillId);
|
||||
final long killId = seckillId;
|
||||
LOGGER.info("开始秒杀五(正常、数据库锁最优实现)");
|
||||
LOGGER.info("开始秒杀六(正常、数据库锁最优实现)");
|
||||
for(int i=0;i<1000;i++){
|
||||
final long userId = i;
|
||||
Runnable task = new Runnable() {
|
||||
@@ -162,12 +188,12 @@ public class SeckillController {
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
@ApiOperation(value="秒杀六(进程内队列)",nickname="科帮网")
|
||||
@ApiOperation(value="秒杀柒(进程内队列)",nickname="科帮网")
|
||||
@PostMapping("/startQueue")
|
||||
public Result startQueue(long seckillId){
|
||||
seckillService.deleteSeckill(seckillId);
|
||||
final long killId = seckillId;
|
||||
LOGGER.info("开始秒杀六(正常)");
|
||||
LOGGER.info("开始秒杀柒(正常)");
|
||||
for(int i=0;i<1000;i++){
|
||||
final long userId = i;
|
||||
Runnable task = new Runnable() {
|
||||
|
||||
Reference in New Issue
Block a user