码迷,mamicode.com
首页 > 其他好文 > 详细

项目中并发(一)

时间:2018-03-17 19:46:22      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:object   setname   run   bsp   mil   nts   并发   前台   latch   

并发现象

public class Demo {
    public Integer count = 0;
    public static void main(String[] args) {
        final Demo demo = new Demo();
        Executor executor = Executors.newFixedThreadPool(10);
        for(int i=0;i<1000;i++){
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    demo.count++;
                }
            });
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("final count value:"+demo1.count);
    }
}

  并发导致读到脏数据。

实际到数据库中的操作

  充血模型遭遇并发(将行为和属性都加上,简单理解为bean加上数据库的操作方法)

@Component
public class Demo2 {
    @Autowired
    TestNumDao testNumDao;
    @Transactional
    public void test(){
        TestNum testNum = testNumDao.findOne("1");
        testNum.setCount(testNum.getCount()+1);
        testNumDao.save(testNum);
    }
}
//多线程进行操作
Demo2 demo2;
public String test(){
    Executor executor = Executors.newFixedThreadPool(10);
    for(int i=0;i<1000;i++){
        executor.execute(new Runnable() {
            @Override
            public void run() {
                demo2.test();
            }
        });
    }
    return "test";
}
final count value:973

  贫血模型遭遇并发(进行行为和属性的分离,分离出dao)

@RequestMapping("testSql")
    @ResponseBody
    public String testSql() throws InterruptedException {
        final CountDownLatch countDownLatch = new CountDownLatch(1000);
        long start = System.currentTimeMillis();
        Executor executor = Executors.newFixedThreadPool(10);
        for(int i=0;i<1000;i++){
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    jdbcTemplate.execute("update test_num set count = count + 1 where id = ‘1‘");
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        long costTime =System.currentTimeMillis() - start;
        System.out.println("共花费:"+costTime+" s");
        return "testSql";
    }
 count : 1000

修改个人信息:非并发

//Transaction start
User user = userDao.findById("1");
user.setName("newName");
user.setAge(user.getAge()+1);
...//其他耗时操作
userDao.save(user);
//Transaction commit

修改商品信息:并发,场景乐观

class Goods{
    @Version
//使用乐观锁,修改成功后版本号变化,另一个操作员失败
    int version;
}
//Transaction start
try{
    Goods goods = goodsDao.findById("1");
    goods.setName("newName");
    goods.setPrice(goods.getPrice()+100.00);
    ...//其他耗时操作
    goodsDao.save(goods);
}catch(org.hibernate.StaleObjectStateException e){
    //返回给前台
}
//Transaction commit

扣除账号余额:并发,场景不乐观

update set balance = balance – money where userId = ? and balance >= money;
update stock = stock – number where goodsId = ? and stock >= number ; 
然后在后台 查看返回值是否影响行数为1,判断请求是否成功,利用数据库保证并发。
数据库行级锁

 

项目中并发(一)

标签:object   setname   run   bsp   mil   nts   并发   前台   latch   

原文地址:https://www.cnblogs.com/test1234/p/8591744.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!