足够能支持一般并发,高并发可在这基础上使用redis原子性
UserPrice.java
package com.andnnl.userlock;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by andnnl on 2017/7/31.
*/
public class UserPrice {
private static UserPrice instance;
private static Map<String, byte[]> lockMap = new ConcurrentHashMap<>();
private static Map<String, User> userMap = new ConcurrentHashMap<>();
private UserPrice() {
}
public synchronized static UserPrice getInstance(String uid) {
if (instance == null)
instance = new UserPrice();
byte[] b = lockMap.get(uid);
if (b == null) {
lockMap.put(uid, new byte[]{});
}
return instance;
}
public boolean checkPrice(String uid, int price) {
synchronized (lockMap.get(uid)) {
User user = userMap.get(uid);
if (user == null) {
user = new User(uid, 100000000);
userMap.put(uid, user);
}
if (user.price - price >= 0) {
return true;
}
}
return false;
}
public boolean deduct(String uid, int price) {
synchronized (lockMap.get(uid)) {
if (checkPrice(uid, price)) {
User user = userMap.get(uid);
user.price -= price;
}
}
return false;
}
static void print() {
for (Map.Entry<String, User> entry : userMap.entrySet()) {
System.out.println(entry.getValue().toString());
}
}
public static void main(String[] args) {
for (int i = 0; i < 300; i++) {
final int finalI = i % 3;
new Thread(new Runnable() {
@Override
public void run() {
String uid = "uid" + finalI;
UserPrice up = UserPrice.getInstance(uid);
while (true) {
if (up.checkPrice(uid, 3)) {
up.deduct(uid, 3);
}
}
}
}).start();
}
while (true) {
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
print();
System.out.println();
}
}
}
User.java
package com.andnnl.userlock;
/**
* Created by andnnl on 2017/7/31.
*/
public class User {
String uid;
int price;
public User() {
}
public User(String uid, int price) {
this.uid = uid;
this.price = price;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "User{" +
"uid='" + uid + '\'' +
", price=" + price +
'}';
}
}