多线程现场事故解决案例
1.最近做一个项目,需要有分配授权数量,但初始化必须是0 2.授权的数量在使用中必须一个个扣除 3.每次消耗都要进行记录,然后再扣减数量 看起来上面三部都没问题, 问题就在第三步呀,消耗记录报错后,数量没有来得及扣除,这样相当与白送了一键给对方,为什么呢 ,因为你是用了就要扣除,我管你报不报错,不够你就在买。 举个例子,你买两个包子,老板把俩包子给你了,你吃一个,然后想再吃一个,啪,掉地上了,这时候你再付钱说只给你一个包子的钱,地上那个我没吃,你看老板抽不抽你就完事了。 下面进入正题!!!!
package com.wangbiao.sqilte.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wangbiao.sqilte.entity.Student;
import com.wangbiao.sqilte.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
/**
* (Student)表控制层
*
* @author makejava
* @since 2023-03-26 21:33:55
*/
@Slf4j
@RestController
@RequestMapping
public class StudentController {
/**
* 服务对象
*/
private static ReentrantLock object = new ReentrantLock();
static ExecutorService executorService = new ThreadPoolExecutor(5, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));
private final StudentService studentService;
public StudentController(StudentService studentService) {
this.studentService = studentService;
}
/**
* @return 查询结果
*/
@GetMapping("/test")
public Object queryByPage() {
//从0开始
AtomicInteger integer = new AtomicInteger(0);
for (int i = 1; i <= 50; i++) {
Thread runnable = new Thread() {
@Override
public void run() {
try {
object.lock();
integer.getAndAdd(1);
int b= integer.get();
System.out.println("2222222222222222:" + b);
//让等于50抛出异常
if(b==50){
int c=b/0;
}
//问题就在b==50,这式上面是50,下面才49
AtomicInteger atomicInteger = new AtomicInteger(getAdd());
atomicInteger.getAndAdd(1);
int i1 = atomicInteger.get();
System.out.println("11111111111:" + i1);
//每次拿出来叠加后更新
update(i1);
}catch (Exception e){
log.error("错啦!!!!");
}finally {
object.unlock();
}
}
};
executorService.submit(runnable);
}
return null;
}
public int getAdd() {
//在数据库里面,这里一开始也是返回0
Student student = studentService.getOne(new LambdaQueryWrapper<Student>().eq(Student::getId, 1));
return student.getAge();
}
public void update(int a) {
studentService.update(null, new LambdaUpdateWrapper<Student>().set(Student::getAge, a).eq(Student::getId, 1));
}
}

优化后代码
package com.wangbiao.sqilte.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wangbiao.sqilte.entity.Student;
import com.wangbiao.sqilte.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
/**
* (Student)表控制层
*
* @author makejava
* @since 2023-03-26 21:33:55
*/
@Slf4j
@RestController
@RequestMapping
public class StudentController {
/**
* 服务对象
*/
private static ReentrantLock object = new ReentrantLock();
static ExecutorService executorService = new ThreadPoolExecutor(5, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));
private final StudentService studentService;
private final TransactionTemplate transactionTemplate;
public StudentController(StudentService studentService,
TransactionTemplate transactionTemplate) {
this.studentService = studentService;
this.transactionTemplate = transactionTemplate;
}
/**
* @return 查询结果
*/
@GetMapping("/test")
public Object queryByPage() {
//从0开始
AtomicInteger integer = new AtomicInteger(0);
//无返回式编程事务
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
for (int i = 1; i <= 50; i++) {
Thread runnable = new Thread() {
@Override
public void run() {
try {
object.lock();
integer.getAndAdd(1);
int b = integer.get();
System.out.println("2222222222222222:" + b);
//让等于50抛出异常
if (b == 50) {
int c = b / 0;
}
//问题就在b==50,这式上面是50,下面才49
AtomicInteger atomicInteger = new AtomicInteger(getAdd());
atomicInteger.getAndAdd(1);
int i1 = atomicInteger.get();
System.out.println("11111111111:" + i1);
//每次拿出来叠加后更新
update(i1);
} catch (Exception e) {
//发生异常进行回滚 }}}}}优化点
transactionStatus.setRollbackOnly();
log.error("错啦!!!!");
} finally {
object.unlock();
}
}
};
executorService.submit(runnable);
}
}
});
return null;
}
public int getAdd() {
//在数据库里面,这里一开始也是返回0
Student student = studentService.getOne(new LambdaQueryWrapper<Student>().eq(Student::getId, 1));
return student.getAge();
}
public void update(int a) {
studentService.update(null, new LambdaUpdateWrapper<Student>().set(Student::getAge, a).eq(Student::getId, 1));
}
}
本文来自博客园,作者:余生请多指教ANT,转载请注明原文链接:https://www.cnblogs.com/wangbiaohistory/p/17271028.html

浙公网安备 33010602011771号