package org.gjp;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.ExistsBuilder;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
public class ZkCreateNode {
public byte[] getData(CuratorFramework client,final String path){
byte [] b = null;
try {
b = client.getData().forPath(path);
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
/**
* 检查节点是否存在
*
* @param client
* @param path
* @return
*/
public Stat checkNode(CuratorFramework client, String path) {
ExistsBuilder eb = client.checkExists();
Stat stat = null;
try {
stat = eb.forPath(path);
if (stat != null) {
//System.out.println(stat);
System.out.println("version:" + stat.getVersion());
} else {
System.out.println(" null ......");
}
} catch (Exception e) {
e.printStackTrace();
}
return stat;
}
/**
* 创建节点
*
* @param client
* @param path
* @return
*/
public String createNode(CuratorFramework client, final String path, final String value) {
String result = "";
try {
result = client.create().forPath(path, value.getBytes());
System.out.println("res:" + result);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 设置具有序列化的临时节点
*
* @param client
* @param path
* @param value
* @return
*/
public String createModeEphSeqNode(CuratorFramework client, final String path, final String value) {
String result = "";
try {
result = client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, value.getBytes());
System.out.println("res:" + result);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 删除节点
*
* @param client
* @param path
* @return
*/
public boolean deleteNode(CuratorFramework client, final String path) {
boolean result = true;
try {
client.delete().forPath(path);
} catch (Exception e) {
result = false;
e.printStackTrace();
}
return result;
}
/**
* 修改节点值
*
* @param client
* @param path
* @param val
* @return
*/
public boolean changeNodeData(CuratorFramework client, final String path, final String val) {
boolean result = true;
try {
client.setData().forPath(path, val.getBytes());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
public void getNodeChild(CuratorFramework client, final String path) throws Exception {
List
for (String item : pathChild) {
System.out.println("child:" + item);
}
}
/**
* 分布式锁 方式1
*
* @param client
* @param path
* @param val
*/
public boolean disLock(CuratorFramework client, final String path, final String val) {
boolean result = false;
// 首先查看节点是否存在
Stat stat = checkNode(client, path);
if (null == stat) {
// 创建节点
String res = createNode(client, path, val);
if (null != res && "".equals(res.trim())) {
// 创建节点成功
InterProcessMutex lock = new InterProcessMutex(client, path);
try {
if (lock.acquire(10 * 1000, TimeUnit.SECONDS)) {
// 业务逻辑内容。。。。。。。
System.out.println(Thread.currentThread().getName() + " hold lock");
Thread.sleep(5000L);
System.out.println(Thread.currentThread().getName() + " release lock");
result = true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
lock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return result;
}
/** 分布式锁 方式2
* 1.当商品抢购时,把抢购商品的 发布数量和购买数量传入,当用户支付前执行disLockNum 方法在zookeeper中记录用户已经准备支付的商品数量,
* 2.当发布商品修改商品数量时,设置zookeeper 中数量为0
* 3.支付失败时,从zookeeper中减去支付失败的商品数量;
* @param client
* @param path
* @param num:购买数量
* @param releaseNum:剩余数量
* @return
*/
public boolean disLockProductAddNum(CuratorFramework client, final String path, final Double num, final Double releaseNum) {
boolean result = false;
InterProcessMutex lock = new InterProcessMutex(client, path);
try {
if (lock.acquire(100 * 1000, TimeUnit.SECONDS)) {
// 首先查看节点是否存在
Stat stat = checkNode(client, path);
if (null == stat) {
// 创建节点
String res = createNode(client, path, num.toString());
if (null != res && "".equals(res.trim())) {
try {
result = true;
} catch (Exception e) {
e.printStackTrace();
}
}
}else{
//获取zookeeper中的数量
byte[] preNum = getData(client, path);
if(null != preNum){
Double preTotal = 0.0;
if(preNum.length >0){
preTotal = Double.parseDouble(new String(preNum));
}
Double total = preTotal.doubleValue() + num.doubleValue();
if(total.doubleValue() < releaseNum.doubleValue()){
boolean b = changeNodeData(client, path, total.toString());
if(b){
result = true;
return result;
}else{
//操作失败
return false;
}
}else{
//库存不足
return false;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
lock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
/**
* 支付失败后,把购买数量从zookeeper中去除
* @param client
* @param path
* @param num 减少的数量
* @return
*/
public boolean disLockProductdReduceNum(CuratorFramework client, final String path, final Double num) {
boolean result = false;
//获取zookeeper中的数量
byte[] preNum = getData(client, path);
if(null != preNum){
Double preTotal = 0.0;
if(preNum.length >0){
preTotal = Double.parseDouble(new String(preNum));
Double total = preTotal.doubleValue() - num.doubleValue();
if(total.doubleValue() >=0){
boolean b = changeNodeData(client, path, total.toString());
if(b){
result = true;
return result;
}
}
}
}
return result;
}
}
测试代码:
package org.gjp;
import java.util.Calendar;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.curator.framework.CuratorFramework;
public class ProductNumThread {
public static void main(String[] args) {
ExecutorService exe = Executors.newFixedThreadPool(70);
final long start =Calendar.getInstance().getTimeInMillis();
for (int i = 1; i < 1990; i++) {
final double step = i;
final double iN = 1;
exe.execute(new Runnable() {
double num = iN; //购买数量
double storeNum = 2000;//发布数量
String path ="/orage_id"; //商品id
public void run() {
CuratorFramework client = ZkListenTest.getClient();
ZkCreateNode node = new ZkCreateNode();
boolean flag = node.disLockProductAddNum(client, path, num, storeNum);
System.out.println("flag:"+flag);
boolean pay = false;
if(flag){
pay = true; //开始支付货款
}
if(!pay){
//支付失败时
node.disLockProductdReduceNum(client, path, num);
}
if(null != client){
client.close();
}
if(step >1990){
long end = Calendar.getInstance().getTimeInMillis();
System.out.println("==========================="+(end -start));
}
}
});
}
}
}