多线程现场事故解决案例

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));

    

 

以上是关于多线程现场事故解决案例的主要内容,如果未能解决你的问题,请参考以下文章

凌晨1点突发致命生产事故,人工多线程来破局!

凌晨1点突发致命生产事故,人工多线程来破局!

HBase案例 | 20000个分区导致HBase集群宕机事故处理

同事多线程使用不当导致OOM,被我怒怼了

同事多线程使用不当导致OOM,被我怼了一顿

逃逸序列是啥