zookeeper实现fifo以及并发访问删除

zookeeper实现fifo以及并发访问删除

package cn.sniper.zookeeper;
import java.io.IOException;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;
public class ZookeeperUtil {
 
 @Test
 public void helloword() {
  //端口默认是2181
  //String connectString = "192.168.1.231";
  String connectString = "192.168.1.231:2181";
  int sessionTimeout = 20000;
  
  try {
   ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
    public void process(WatchedEvent event) {
     System.out.println(event);
    }
   });
   
   System.out.println(zk);
   zk.close();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
 
 @Test
 public void create() {
  String connectString = "192.168.1.231:2181";
  int sessionTimeout = 20000;
  
  try {
   ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
    public void process(WatchedEvent event) {
     System.err.println("事件类型:" + event.getType());
    }
   });
   
   //创建节点 
   zk.create("/sniper1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
   
   zk.close();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (InterruptedException e) {
   e.printStackTrace();
  } catch (KeeperException e) {
   e.printStackTrace();
  }
 }
 
 @Test
 public void fifoIn() {
  String connectString = "192.168.1.231,192.168.1.232,192.168.1.233";
  int sessionTimeout = 50000;
  
  try {
   ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
    public void process(WatchedEvent event) {
     System.err.println("事件类型:" + event.getType());
    }
   });
   
   //每个客户端连进来的时候,都在fifo下创建一个有序节点  模拟10个客户端连接进入
   for(int i=0; i<10; i++) {
    zk.create("/fifo/", String.valueOf(System.currentTimeMillis()).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
   }
   
   zk.close();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (InterruptedException e) {
   e.printStackTrace();
  } catch (KeeperException e) {
   e.printStackTrace();
  }
 }
 
 @Test
 public void fifoOut() {
  String connectString = "192.168.1.231,192.168.1.232,192.168.1.233";
  int sessionTimeout = 30000;
  
  try {
   ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
    public void process(WatchedEvent event) {
     System.err.println("事件类型:" + event.getType());
    }
   });
   
   List children = zk.getChildren("/fifo", new Watcher() {
    public void process(WatchedEvent event) {
     System.err.println("事件类型:" + event.getType());
    }
   });
   
   //由于节点的有序性,将节点用treeSet排序一下,取得第一个元素,就可以做到先进先出队列了
   TreeSet set = new TreeSet(children);
   
   String child = set.first();
   
   System.err.println(child);
   
   zk.delete("/fifo/"+child, -1);
   
   zk.close();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (InterruptedException e) {
   e.printStackTrace();
  } catch (KeeperException e) {
   e.printStackTrace();
  }
 }
 
 /**
  * 多线程创建有序节点不存在问题
  * @throws Exception
  */
 public static void fifoInMultiThread() throws Exception {
  //int nThreads = Runtime.getRuntime().availableProcessors();
  
  int nThreads = 20;
  final ExecutorService service = Executors.newFixedThreadPool(nThreads);
  
  final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 30000, new Watcher() {
   public void process(WatchedEvent evet) {
    
   }
  });
  
  final long begin = System.currentTimeMillis();
  
  for(int i=0; i<1000; i++) {
   final int j = i;
   service.execute(new Runnable() {
    public void run() {
     try {
      zk.create("/fifo/", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
     } catch (KeeperException e) {
      e.printStackTrace();
     } catch (InterruptedException e) {
      e.printStackTrace();
     } finally {
      if(j == 999) {
       try {
        zk.close();
        service.shutdown();
        System.err.println(System.currentTimeMillis() - begin);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
      }
     }
    }
   });
  }
 }
 
 @Test
 public void size() throws Exception {
  final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 50000, new Watcher() {
   public void process(WatchedEvent evet) {
    
   }
  });
  
  System.out.println(zk.getChildren("/fifo", new Watcher() {
   public void process(WatchedEvent evet) {
    
   }
  }).size() + " =========================");
  
  zk.close();
 }
 
 /**
  * 多线程取出节点并且删除节点存在问题,synchronized解决方案
  * @throws Exception
  */
 public static void fifoOutMultiThread() throws Exception {
  int nThreads = 20;
  final ExecutorService service = Executors.newFixedThreadPool(nThreads);
  
  final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 50000, new Watcher() {
   public void process(WatchedEvent evet) {
    
   }
  });
  
  final long begin = System.currentTimeMillis();
  
  for(int i=0; i<1000; i++) {
   final int j = i;
   service.execute(new Runnable() {
    public void run() {
     try {
      synchronized (ZookeeperUtil.class) {
       List children = zk.getChildren("/fifo", new Watcher() {
        public void process(WatchedEvent arg0) {
         
        }
       });
       
       if(children != null && children.size() > 0) {
        TreeSet set = new TreeSet(children);
        String pop = set.first();
        
        System.err.println(pop);
        
        zk.delete("/fifo/"+pop, -1);
       }
      }
     } catch (KeeperException e) {
      e.printStackTrace();
     } catch (InterruptedException e) {
      e.printStackTrace();
     } finally {
      if(j == 999) {
       try {
        zk.close();
        service.shutdown();
        System.err.println(System.currentTimeMillis() - begin);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
      }
     }
    }
   });
  }
 }
 
 /**
  * 多线程取出节点并且删除节点存在问题,读写锁方式
  * @throws Exception
  */
 public static void fifoOutMultiThreadLock() throws Exception {
  final ReadWriteLock rwl = new ReentrantReadWriteLock();
  
  int nThreads = 20;
  final ExecutorService service = Executors.newFixedThreadPool(nThreads);
  
  final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 50000, new Watcher() {
   public void process(WatchedEvent evet) {
    
   }
  });
  
  final long begin = System.currentTimeMillis();
  
  for(int i=0; i<1000; i++) {
   final int j = i;
   service.execute(new Runnable() {
    public void run() {
     try {
      rwl.readLock().lock();
       //取得fifo下的所有直接下级节点
       List children = zk.getChildren("/fifo", new Watcher() {
        public void process(WatchedEvent event) {
         
        }
       });
       
       //用treeset排好序
       TreeSet set = new TreeSet(children);
       //取出第一个,即最先进入的一个
       String pop = set.first();
       //判断是否存在
       Stat stat = zk.exists("/fifo/"+pop, new Watcher() {
        public void process(WatchedEvent event) {
         
        }
       });
      
      if(stat != null) {
       rwl.readLock().unlock();
       
       rwl.writeLock().lock();
        //用于多线程读的因素,有可能第一条线程读到节点还存在,紧接着第二条线程就把该节点删除了,所以,加了写锁之后还需要判断一次节点是否存在
        stat = zk.exists("/fifo/"+pop, new Watcher() {
         public void process(WatchedEvent event) {
          
         }
        });
        
        if(stat != null) {
         System.err.println(pop);
         zk.delete("/fifo/"+pop, -1);
        }
       rwl.writeLock().unlock();
       rwl.readLock().lock();
      }
      rwl.readLock().unlock();
     } catch (KeeperException e) {
      e.printStackTrace();
     } catch (InterruptedException e) {
      e.printStackTrace();
     } finally {
      if(j == 999) {
       try {
        zk.close();
        service.shutdown();
        System.err.println(System.currentTimeMillis() - begin);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
      }
     }
    }
   });
  }
 }
 
 public static void main(String[] args) throws Exception {
  //fifoInMultiThread();
  //fifoOutMultiThread();
  //fifoOutMultiThreadLock();
 }
 
}

转载于:https://my.oschina.net/sniperLi/blog/499413

你可能感兴趣的:(zookeeper实现fifo以及并发访问删除)