项目中并发

Posted test1234

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目中并发相关的知识,希望对你有一定的参考价值。

并发现象

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,判断请求是否成功,利用数据库保证并发。
数据库行级锁

 

以上是关于项目中并发的主要内容,如果未能解决你的问题,请参考以下文章

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

golang代码片段(摘抄)

全栈编程系列SpringBoot整合Shiro(含KickoutSessionControlFilter并发在线人数控制以及不生效问题配置启动异常No SecurityManager...)(代码片段

多个用户访问同一段代码

java开发的项目案例,大厂内部资料