獲取Spring中的bean,使得線程安全性獲得保障

在構造多線程的時候,線程自己也須要託管到spring上去運行,因爲須要注入一些變量致使原來使用單例的變量使用的是成員變量,使得注入值的時候發生了「競態」致使了線程不安全。例如原來寫的代碼: java


@Service("winningCodeService")
public class WinningCodeServiceImpl implements WinningCodeService {

    private static Log log = LogFactory.getLog(WinningCodeServiceImpl.class);
    private static BlockingQueue<WinningCode> winningCodeQueue = new LinkedBlockingQueue<WinningCode>();
    private static BlockingQueue<ChargeResponse> sendToPhpQueue = new LinkedBlockingQueue<ChargeResponse>();

    private String dir;//winningCodeQueue鎖處在的目錄
    private String encode;//編碼格式
    private String toPhpUrl;//到PHP的地址

    @Autowired
    private SendToDDTApi sendToDDTApi;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private SendFinalResultToPhp sendFinalResultToPhp;

    @Autowired
    private ChargeRecodeDao chargeRecodeDao;

    @Autowired
    private WinningCodeDao winningCodeDao;

    @Override
    public void putToDDTApi(WinningCode winningCode) {
        log.info(winningCode);
        winningCodeQueue.offer(winningCode);
        log.debug("插入前的數量:"+winningCodeQueue.size());
    }


    @Override
    public void beginSendToDDT(final String url) {
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                taskSendToDDT(url);
            }
        });

    }

    private void taskSendToDDT(String url) {
        while (true) {
            WinningCode winningCode = null;
            try {
                log.debug("獲取時候的數量:"+winningCodeQueue.size());
                winningCode = winningCodeQueue.take();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            sendToDDTApi.setWinningCode(winningCode);//在該狀態下會發生競態致使程序出錯。
            sendToDDTApi.setUrl(url);
            threadPoolTaskExecutor.execute(sendToDDTApi);
        }
    }


  
}



線程代碼



@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class SendToDDTApi implements Runnable {
    private static Log log = LogFactory.getLog(SendToDDTApi.class);
    private String url;

    @Autowired
    private PrizeCodeLibraryDao prizeCodeLibraryDao;

    @Autowired
    private WinningCodeDao winningCodeDao;
    @Autowired
    private WinningCodeService winningCodeService;

    @Autowired
    private ResendService resendService;

    private WinningCode winningCode;

    private String appKey;

    private String appSecret;

    @Override
    public void run() {
        try {
            pushToDDT();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void pushToDDT() throws InterruptedException {
        String serialNumber = winningCode.getSerialNumber();
        String md5 = MD5.getMD5Code(winningCode.getPrizedCode());
        PrizeCodeLibrary prizeCode = prizeCodeLibraryDao.findByPrizeCode(md5);
        if(prizeCode==null){
            throw new PrizeException("獎碼查詢爲空");
        }
        winningCode.setAmount(prizeCode.getAmount());
        winningCode.setRank(prizeCode.getRank());
        winningCode.setExpiryTime(new Date());
        WinningCode win = winningCodeDao.findWinningCodeBySerialNumber(serialNumber);
        if(win==null){
            winningCodeDao.insertWinningCode(winningCode);
        }
        String result = null;
        try{
            result = SendRequest(winningCode);
        }catch (Exception e) {
            winningCodeService.saveChargeRecode(winningCode.getSerialNumber(),null);
            winningCodeDao.updateChargeStatBySerialNumber(winningCode.getSerialNumber(), ChargeStatus.CHARGE_FAILURE.getCode());
            resendService.resendOrSendFailure(serialNumber);
            log.error(e);
        }
        log.info("返回的值:" + result);
        if(result!=null){
            checkResult(result, winningCode);
        }

    }

}




如今在服務代碼中加入如下, spring


@Autowired
private BeanFactory beanFactory;


而且將線程代碼添加如下代碼讓該線程變爲多實例 安全


@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)




而且在服務代碼中,根據bean的名字獲取對應名字。就能夠變成局部變量,使得線程安全了。 多線程

相關文章
相關標籤/搜索