美文网首页游戏开发
数据库多线程操作的弊端及简单有效的解决方案

数据库多线程操作的弊端及简单有效的解决方案

作者: higher2017 | 来源:发表于2016-12-15 00:02 被阅读464次

    数据库操作是异步的,在高并发的情况下有可能出现以下的情形:

    1、线程A对数据库的表table_1进行插入操作,同时另一线程B同样对表table_2进行查询最新数据操作。这个时候线程B理想的获取值应该是线程A插入的数据,但实际上却不一定取得理想值。

    2、频繁操作数据库不仅会造成数据不能及时更新,同时还会大量消耗机器的性能。

    一般不涉及并发操作的可进行下面的数据库操作

    1.1 1.2 1.3

    1.1:Service主操作:包含dao对数据库的增查操作
    1.2:Service业务操作1:查找并进行逻辑运算
    1.3:Service业务操作2:插入数据

    下面介绍一种简单有效的解决方案(轻量级):使用public static对插入数据进行缓存:

    基础Service:

    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    
    @Service("dataBasesConcurrencyServ")
    public class DataBasesConcurrencyServImpl implements  DataBasesConcurrencyServ{
        @Autowired
        private DouniuDao douniuDao;
        private static Douniu douniuCache = null;
        private String douniuCacheLockStr = "douniuCacheLockStr";
        
        //其它类只能够调用该方法保存douniu,以及setDouniuCache,以保证数据库的线程安全
        public Douniu setDouniu(Douniu douniu) {
            // 代码块加锁保障线程安全
            synchronized (douniuCacheLockStr.intern()) {
                douniuDao.save(douniu);
                setDouniuCache(douniu);
                return douniu;
            }
        }
    
        private void setDouniuCache(Douniu douniu) {
            if (douniu == null)
                return;
            douniuCache = new Douniu();
            BeanUtils.copyProperties(douniu, douniuCache);
        }
    
        public Douniu getDouniuCache() {
            synchronized (douniuCacheLockStr.intern()) {
                if (douniuCache == null) {
                    // 启动服务器时,第一条缓存应该从数据库拿
                    douniuCache = douniuDao.loadNew(1);
                }
                return douniuCache;
            }
        }
    }
    

    Control层操作:

    import java.util.HashMap;
    import java.util.Map;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import com.sun.net.httpserver.Authenticator.Success;
    
    @RequestMapping("/dataBasesConcurrencyCon")
    @Controller
    public class DataBasesConcurrencyCon {
        @Autowired
        private DataBasesConcurrencyServ dataBasesConcurrencyServ;
        
        /**
         * 获取douniu实时数据(并保证数据库的线程安全)
         * @return
         */
        @RequestMapping("/getDouniuNow")
        @ResponseBody
        public Object getDouniuNow(){
            try{
                Map<String,Object> successMap = new HashMap<String, Object>();
                successMap.put("sccessMap", true);
                successMap.put("douniu",dataBasesConcurrencyServ.getDouniuCache());
                return successMap;
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        @RequestMapping("/saveDouniu")
        @ResponseBody
        public Object saveDouniu(Douniu save){
            try{
                dataBasesConcurrencyServ.setDouniu();
                Map<String,Object> successMap = new HashMap<String, Object>();
                successMap.put("sccessMap", true);
                return successMap; 
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    以上就是通过静态成员变量来进行缓存操作的简单有效方法。

    相关文章

      网友评论

        本文标题:数据库多线程操作的弊端及简单有效的解决方案

        本文链接:https://www.haomeiwen.com/subject/oiakmttx.html