spring單例與線程安全,並行調用服務加速響應


問題:ssm框架,spring中controller和service都是單例的,那是怎麼保證線程安全呢?
通過threadLocal保證,
實際一個實例,tomcat中線程池執行任務時,獲取單例的副本,每個線程的執行都是操作單例的副本
那既然有單例的副本,此時還是單例的嗎?????
https://www.cnblogs.com/-zhuang/articles/10607877.html

所有線程共享
類中定義 :static DateFormat ;

線程內共享:
類中定義-此時每個線程內部有一個新的對象,線程內部單獨有一個對象,不存在線程安全的問題
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() ;

方法內共享:
方法內聲明 DateFormat format;
說明:使用 ThreadLocal, 也是將共享變量變爲獨享,線程獨享肯定能比方法獨享在併發環境中能減少不少創建對象的開銷。如果對性能要求比較高的情況下,一般推薦使用這種方法。


思路:
controller中service並行調用 service中的慢方法:
controller中 線程池
實現callable的實現類,直接將controller中的service和參數傳入
線程池submit
future.get獲取返回內容實例:

@Controller
@RequestMapping(value = "")
public class ReportSetController {
    static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ReportSetController.class);
    static ExecutorService pool = Executors.newFixedThreadPool(10);

     @Autowired
    OrganizationService organizationService;

    @RequestMapping(value="/reportset/toEdit.action")
    public String toEdit( ModelMap modelMap,ServletRequest request,String reportsetIdStr ){
        // 預處理 。。。 省略

        // 老的寫法如下:串行調用
        //        String treecontent1 = JSON.toJSONString(treeService.getOrganTree(ReportsetUserType.TO, reportsetId));
        // 新的寫法如下: 並行調用,開啓新的線程
        Future<String> submit = pool.submit(new TreeContentTask(treeService, ReportsetUserType.TO, reportsetId));
        String str = reportsetService.getReportsetBoardStrList(reportsetId);
        List<DashboardBoard> dashboardBoards = dashboardService.listUserDashboards(RSBIUtils.getLoginUserInfo().getUserId());
        String treecontent = null;
        try {
            treecontent = submit.get();
        } catch (InterruptedException e) {
            logger.error("組織關係獲取失敗", e);
        } catch (ExecutionException e) {
            logger.error("組織關係獲取失敗", e);
        }
        modelMap.put("treecontent", treecontent);
        return "reportset/reportset-edit";
    }
}

public class TreeContentTask implements Callable<String> {

    OrganizationTreeService service ;
    ReportsetUserType type;
    Integer reportsetId;

    // 有線程安全問題?同一個service
    public TreeContentTask(OrganizationTreeService service, ReportsetUserType type, Integer reportsetId){
        this.service = service;
        this.type = type;
        this.reportsetId = reportsetId;
    }

    @Override
    public String call() throws Exception {
        OrganTreeCoreDto organTree = service.getOrganTree(type, reportsetId);
        return JSON.toJSONString(organTree);
    }
}


網上怎麼解決的?
controller中創建任務  線程池在service中
https://blog.csdn.net/Hello_Ray/article/details/83340064

微服務優化之並行調用
https://blog.csdn.net/tidu2chengfo/article/details/80275064

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章