更新時間:2021-03-26 16:11:09 來源:動力節(jié)點 瀏覽2714次
在程序的應用程序中,用戶或請求的數(shù)量達到一定數(shù)量,并且無法避免并發(fā)請求.由于對接口的每次調(diào)用都必須在返回時終止,因此,如果接口的業(yè)務相對復雜,則可能會有多個用戶.調(diào)用接口時,該用戶將凍結(jié).
以下內(nèi)容將介紹解決此問題的巧妙且非常簡單的方法.
請求寫入內(nèi)存
我們可以將每個請求封裝為一個對象,然后將其寫入內(nèi)存.
@Getter
@Setter
private static class CallVo{//請求對象
private Long param1;//參數(shù)1
private Integer param2;//參數(shù)2
}
private List<CallVo> callVoList = new ArrayList<>();//請求對象列表
/**
* 接口調(diào)用
* @param callVo
* @return
*/
@Transactional
@RequestMapping(value = "/call",method = {RequestMethod.POST})
public void call(@RequestBody CallVo callVo){
synchronized (syncObject) {
callVoList.add(callVo);//將請求對象寫入內(nèi)存
}
}
多線程處理
創(chuàng)建一個線程以繼續(xù)讀取內(nèi)存中的數(shù)據(jù). 如果被請求對象的收集長度為0多線程技術問題解決,則表明沒有請求. 如果集合中有數(shù)據(jù),請從集合中刪除請求的對象并獲取時間. 根據(jù)相應業(yè)務處理請求的參數(shù).
這達到了將同步轉(zhuǎn)變?yōu)楫惒降哪康模⒑唵蔚亟鉀Q了高并發(fā)性的問題.
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();
//業(yè)務處理
System.out.println(param1+"---"+param2);
}catch (Exception e){
logger.error("接口調(diào)用異常:", 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();
}
/**
* 接口調(diào)用
* @param callVo
* @return
*/
@Transactional
@RequestMapping(value = "/call",method = {RequestMethod.POST})
public GeneralResponse call(@RequestBody CallVo callVo){
synchronized (syncObject) {
callVoList.add(callVo);//將請求對象寫入內(nèi)存
}
return GeneralResponse.success(null);
}
@Getter
@Setter
private static class CallVo{//請求對象
private Long param1;//參數(shù)1
private Integer param2;//參數(shù)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();
//業(yè)務處理
System.out.println(param1+"---"+param2);
}catch (Exception e){
logger.error("接口調(diào)用異常:", e);
}
}
}
@Override
public void destroy() {
runnable = false;
}
}
限制
由于同步是異步的,因此每次請求接口的返回值都是唯一的多線程技術問題解決,因此此方法僅適用于請求者不需要返回的情況.
以上就是動力節(jié)點Java培訓機構(gòu)的小編針對“Java多線程學習處理高并發(fā)問題”的內(nèi)容進行的回答,希望對大家有所幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為你服務。