获取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的名字获取对应名字。就能够变成局部变量,使得线程安全了。 多线程

相关文章
相关标签/搜索