生活随笔
收集整理的這篇文章主要介紹了
获取Spring中的bean,使得线程安全性得到保障
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
在構造多線程的時候,線程本身也需要托管到spring上去運行,由于需要注入一些變量導致原來使用單例的變量使用的是成員變量,使得注入值的時候發(fā)生了“競態(tài)”導致了線程不安全。例如原來寫的代碼:
@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的地址@Autowiredprivate SendToDDTApi sendToDDTApi;@Autowiredprivate ThreadPoolTaskExecutor threadPoolTaskExecutor;@Autowiredprivate SendFinalResultToPhp sendFinalResultToPhp;@Autowiredprivate ChargeRecodeDao chargeRecodeDao;@Autowiredprivate WinningCodeDao winningCodeDao;@Overridepublic void putToDDTApi(WinningCode winningCode) {log.info(winningCode);winningCodeQueue.offer(winningCode);log.debug("插入前的數量:"+winningCodeQueue.size());}@Overridepublic void beginSendToDDT(final String url) {threadPoolTaskExecutor.execute(new Runnable() {@Overridepublic 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);//在該狀態(tài)下會發(fā)生競態(tài)導致程序出錯。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;@Autowiredprivate PrizeCodeLibraryDao prizeCodeLibraryDao;@Autowiredprivate WinningCodeDao winningCodeDao;@Autowiredprivate WinningCodeService winningCodeService;@Autowiredprivate ResendService resendService;private WinningCode winningCode;private String appKey;private String appSecret;@Overridepublic 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("獎碼查詢?yōu)榭?#34;);}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);}}}
現在在服務代碼中加入以下,
@Autowired
private BeanFactory beanFactory;
并且將線程代碼添加以下代碼讓該線程變?yōu)槎鄬嵗?
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
并且在服務代碼中,根據bean的名字獲取對應名字。就可以變成局部變量,使得線程安全了。
??
轉載于:https://my.oschina.net/u/167671/blog/305049
總結
以上是生活随笔為你收集整理的获取Spring中的bean,使得线程安全性得到保障的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。