首先需要在数据库中创建一个表,对应共享资源的id(id)和抢占资源的标识(用户id),(该表和业务无关,只是为了解决抢占分布式资源问题)其它字段信息略
网约车中司机抢单的场景
创建表
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tbl_order 业务表
-- ----------------------------
DROP TABLE IF EXISTS `tbl_order`;
CREATE TABLE `tbl_order` (
`order_id` int(8) NOT NULL,
`order_status` int(8) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_order
-- ----------------------------
INSERT INTO `tbl_order` VALUES ('1', '1');
-- ----------------------------
-- Table structure for tbl_order_lock 锁资源的表
-- ----------------------------
DROP TABLE IF EXISTS `tbl_order_lock`;
CREATE TABLE `tbl_order_lock` (
`order_id` int(8) NOT NULL,
`driver_id` int(8) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建数据库锁的工具类 dao层和实体类省略
package com.online.taxi.order.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import com.online.taxi.order.dao.TblOrderLockDao;
import com.online.taxi.order.entity.TblOrderLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.Data;
@Service
@Data
public class MysqlLock implements Lock {
@Autowired
private TblOrderLockDao mapper;
private ThreadLocal<TblOrderLock> orderLockThreadLocal ;
@Override
public void lock() {
// 1、尝试加锁
if(tryLock()) {
System.out.println("尝试加锁");
return;
}
// 2.休眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 3.递归再次调用
lock();
}
/**
* 非阻塞式加锁,成功,就成功,失败就失败。直接返回
*/
@Override
public boolean tryLock() {
try {
TblOrderLock tblOrderLock = orderLockThreadLocal.get();
mapper.insertSelective(tblOrderLock);
System.out.println("加锁对象:"+orderLockThreadLocal.get());
return true;
}catch (Exception e) {
return false;
}
}
@Override
public void unlock() {
mapper.deleteByPrimaryKey(orderLockThreadLocal.get().getOrderId());
System.out.println("解锁对象:"+orderLockThreadLocal.get());
orderLockThreadLocal.remove();
}
@Override
public void lockInterruptibly() throws InterruptedException {
// TODO Auto-generated method stub
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException{
// TODO Auto-generated method stub
return false;
}
@Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}
}
需要分布式锁解决问题的接口
package com.online.taxi.order.service;
public interface GrabService {
/**
* 司机抢单
* @param orderId
* @param driverId
* @return
*/
public String grabOrder(int orderId , int driverId);
}
分布式锁解决问题实现类
package com.online.taxi.order.service.impl;
import com.online.taxi.order.entity.TblOrderLock;
import com.online.taxi.order.lock.MysqlLock;
import com.online.taxi.order.service.GrabService;
import com.online.taxi.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("grabMysqlLockService")
public class GrabMysqlLockServiceImpl implements GrabService {
@Autowired
private MysqlLock lock;
@Autowired
OrderService orderService;
ThreadLocal<TblOrderLock> orderLock = new ThreadLocal<>();
@Override
public String grabOrder(int orderId, int driverId) {
// 生成 锁
//生成key
TblOrderLock ol = new TblOrderLock();
ol.setOrderId(orderId);
ol.setDriverId(driverId);
orderLock.set(ol);
lock.setOrderLockThreadLocal(orderLock);
// lock
lock.lock();
// 执行业务
try {
System.out.println("司机:"+driverId+" 执行抢单逻辑");
boolean b = orderService.grab(orderId, driverId);
if(b) {
System.out.println("司机:"+driverId+" 抢单成功");
}else {
System.out.println("司机:"+driverId+" 抢单失败");
}
}finally {
// 释放锁
lock.unlock();
}
// 执行业务
return null;
}
}
具体的业务逻辑略掉