专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 学习攻略 Java学习 Java多线程学习处理高并发问题

Java多线程学习处理高并发问题

更新时间:2021-03-26 16:11:09 来源:动力节点 浏览2149次

在程序的应用程序中,用户或请求的数量达到一定数量,并且无法避免并发请求.由于对接口的每次调用都必须在返回时终止,因此,如果接口的业务相对复杂,则可能会有多个用户.调用接口时,该用户将冻结.

以下内容将介绍解决此问题的巧妙且非常简单的方法.

请求写入内存

我们可以将每个请求封装为一个对象,然后将其写入内存.

@Getter
@Setter
private static class CallVo{//请求对象
     private Long param1;//参数1
     private Integer param2;//参数2
}
private List<CallVo> callVoList = new ArrayList<>();//请求对象列表
/**
   * 接口调用
   * @param callVo
   * @return
*/
 @Transactional
 @RequestMapping(value = "/call",method = {RequestMethod.POST})
 public void call(@RequestBody CallVo callVo){
       synchronized (syncObject) {
           callVoList.add(callVo);//将请求对象写入内存
       }
 }

多线程处理

创建一个线程以继续读取内存中的数据. 如果被请求对象的收集长度为0多线程技术问题解决,则表明没有请求. 如果集合中有数据,请从集合中删除请求的对象并获取时间. 根据相应业务处理请求的参数.

这达到了将同步转变为异步的目的,并简单地解决了高并发性的问题.

private Thread thread;
private final Object syncObject = new Object(); // 同步对象
private volatile boolean runnable;
 @Override
 public void run() {
        while (runnable){
            try {
                if (callVoList.size() == 0) {//集合长度为0,证明没有请求
                    Thread.sleep(1000);
                    continue;
                }
                CallVo callVo;
                synchronized (syncObject) {
                    callVo = callVoList.remove(0);
                }
                Long param1 = callVo.getStationId();
                Integer param2 = callVo.getCallType();
               
               //业务处理
                System.out.println(param1+"---"+param2);
               
            }catch (Exception e){
                logger.error("接口调用异常:", e);
            }
        }
  }

完整代码

@RestController
@Slf4j
@RequestMapping("/erpRemote")
public class ErpRemoteController extends BaseController implements DisposableBean, Runnable{
   
    ErpRemoteController(){
        callVoList = new ArrayList<>();
        runnable = true;
        thread = new Thread(this);
        thread.start();
    }
    /**
     * 接口调用
     * @param callVo
     * @return
     */
    @Transactional
    @RequestMapping(value = "/call",method = {RequestMethod.POST})
    public GeneralResponse call(@RequestBody CallVo callVo){
        
        synchronized (syncObject) {
            callVoList.add(callVo);//将请求对象写入内存
        }
        return GeneralResponse.success(null);
    }
    @Getter
    @Setter
    private static class CallVo{//请求对象
        private Long param1;//参数1
        private Integer param2;//参数2
    }
    private List<CallVo> callVoList;
    private Thread thread;
    private final Object syncObject = new Object(); // 同步对象
    private volatile boolean runnable;
    @Override
    public void run() {
        while (runnable){
            try {
                if (callVoList.size() == 0) {//集合长度为0,证明没有请求
                    Thread.sleep(1000);
                    continue;
                }
                CallVo callVo;
                synchronized (syncObject) {
                    callVo = callVoList.remove(0);
                }
                Long param1 = callVo.getStationId();
                Integer param2 = callVo.getCallType();
               
               //业务处理
                System.out.println(param1+"---"+param2);
    
            }catch (Exception e){
                logger.error("接口调用异常:", e);
            }
        }
    }
    @Override
    public void destroy() {
        runnable = false;
    }
}

限制

由于同步是异步的,因此每次请求接口的返回值都是唯一的多线程技术问题解决,因此此方法仅适用于请求者不需要返回的情况.

以上就是动力节点Java培训机构的小编针对“Java多线程学习处理高并发问题”的内容进行的回答,希望对大家有所帮助,如有疑问,请在线咨询,有专业老师随时为你服务。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>