Java多线程学习处理高并发问题
在程序的应用程序中,用户或请求的数量达到一定数量,并且无法避免并发请求.由于对接口的每次调用都必须在返回时终止,因此,如果接口的业务相对复杂,则可能会有多个用户.调用接口时,该用户将冻结.
以下内容是动力节点小编将介绍解决此问题的巧妙且非常简单的方法.
请求写入内存
我们可以将每个请求封装为一个对象,然后将其写入内存.
@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; } }
限制
由于同步是异步的,因此每次请求接口的返回值都是唯一的多线程技术问题解决,因此此方法仅适用于请求者不需要返回的情况.