一.前期准备工作
- 我们需要连接MySQL数据库,我们需要连接数据库的jar包和数据源,这里我用的是c3p0数据源。
- 持久层我们使用mybatis框架。
- 我们在spring配置文件里配置好数据源以及mybatis相关的配置。
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="${url}"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
<property name="initialSize" value="30"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sessionFactoryBean"></property>
<!--配置mapper接口的具体位置-->
<property name="basePackage" value="demo"></property>
</bean>
<!--配置sessionFactoryBean,-->
<bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置mapper.xml的具体位置-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="mapperLocations" value="demo/*.xml"></property>
<property name="dataSource" ref="dataSource"></property>
</bean>
- 数据库里面建好相应的锁表,表的信息如下
二.代码编写阶段
我们模仿创建订单的场景,编写对应的OrderMapper.xml
<insert id="insertOrder" parameterType="Integer">
update method_lock set method_name='createOrder' where id=#{id}
</insert>
**注意此处的 for update 是锁住表的关键**
<select id="queryLock" parameterType="Integer" resultType="String">
select method_name from method_lock where id=#{id} for update
</select>
<delete id="deleteLock" parameterType="Integer">
update method_lock set method_name='' where id =#{id}
</delete>
<update id="incLockCount" parameterType="Integer">
update lock_count set lockcount=lockcount+1 where id=#{id}
</update>
对应的OrderMapper接口
void insertOrder(@Param("id") Integer id);
void deleteLock(@Param("id") Integer id);
String queryLock(@Param("id") Integer id);
创建对应的消费者ConsumerService,lock方法是消费者去获取锁,delete方法是消费者去删除使用过的锁
@Transactional
public boolean lock(){
String method_name=orderMapper.queryLock(1);
if(method_name==null||"".equals(method_name)){
orderMapper.insertOrder(1);
return true;
}
return false;
}
@Transactional
public void deleteLock(){
orderMapper.deleteLock(1);
}
创建对应的消费者Consumer去创建订单
public void createOrder(){
long endtime = System.currentTimeMillis()+3000;
while(System.currentTimeMillis()<endtime){
if(consumerService.lock()){
//这里可以写你想要做的事。
consumerService.deleteLock();
break;
}
//如果没有获取到锁,等待100毫秒再去获取
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试阶段,创建100个消费者同时去创建订单
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:spring-config.xml");
for(int i=0;i<100;i++){
new Thread(new Consumer("consumer:"+i)).start();
}
}