多线程现场事故解决案例
Posted 余生请多指教ANT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程现场事故解决案例相关的知识,希望对你有一定的参考价值。
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));
一点点学习,一丝丝进步。不懈怠,才不会被时代淘汰
以上是关于多线程现场事故解决案例的主要内容,如果未能解决你的问题,请参考以下文章