Use here zookeeper Of EPHEMERAL_SEQUENTIAL Type node and watcher mechanism , To simply implement distributed locks . Main ideas :
1, open 10 Threads , stay disLocks Each node is created with the name sub Of EPHEMERAL_SEQUENTIAL node ;
2, obtain disLocks All child nodes under node , sort , If you have the lowest node number , Get lock ;
3, otherwise watch Nodes in front of themselves , After listening to its deletion , Enter the 2 step ( Redetection sorting is to prevent connection failure of listening nodes , Node deletion caused );
4, Delete itself sub node , Release connection ;
Here's the episode zookeeper Of 4 Node types :public enum CreateMode { /** *
Persistent node : After node creation , Will always be there , Not deleted due to client session failure ; */ PERSISTENT (0, false, false), /** *
Persistent order node : Basic characteristics are consistent with persistent nodes , During node creation ,zookeeper Will automatically append a monotonous number suffix to its name , As a new node name ; */
PERSISTENT_SEQUENTIAL (2, false, true), /** *
Temporary node : After the client session fails or the connection is closed , The node will be deleted automatically , You cannot create a child node under a temporary node , Otherwise, the following error will be reported :org.apache.zookeeper.KeeperException$NoChildrenForEphemeralsException;
*/ EPHEMERAL (1, true, false), /** *
Temporary sequence node : Basic characteristics are consistent with temporary nodes , During node creation ,zookeeper Will automatically append a monotonous number suffix to its name , As a new node name ; */
EPHEMERAL_SEQUENTIAL (3, true, true); private static final Logger LOG =
LoggerFactory.getLogger(CreateMode.class); private boolean ephemeral; private
boolean sequential; private int flag; CreateMode(int flag, boolean ephemeral,
boolean sequential) { this.flag = flag; this.ephemeral = ephemeral;
this.sequential = sequential; } public boolean isEphemeral() { return
ephemeral; } public boolean isSequential() { return sequential; } public int
toFlag() { return flag; } static public CreateMode fromFlag(int flag) throws
KeeperException { switch(flag) { case 0: return CreateMode.PERSISTENT; case 1:
return CreateMode.EPHEMERAL; case 2: return CreateMode.PERSISTENT_SEQUENTIAL;
case 3: return CreateMode.EPHEMERAL_SEQUENTIAL ; default: LOG.error("Received
an invalid flag value to convert to a CreateMode"); throw new
KeeperException.BadArgumentsException(); } } }

Test code :package zookeeper; import org.slf4j.Logger; import
org.slf4j.LoggerFactory; import org.apache.zookeeper.*; import
org.apache.zookeeper.data.Stat; import java.util.List; import
java.io.IOException; import java.util.Collections; import
java.util.concurrent.CountDownLatch; public class DistributedLock implements
Watcher{ private int threadId; private ZooKeeper zk = null; private String
selfPath; private String waitPath; private String LOG_PREFIX_OF_THREAD; private
static final int SESSION_TIMEOUT = 10000; private static final String
GROUP_PATH = "/disLocks"; private static final String SUB_PATH =
"/disLocks/sub"; private static final String CONNECTION_STRING =
"192.168.*.*:2181"; private static final int THREAD_NUM = 10; // Make sure to connect zk success ;
private CountDownLatch connectedSemaphore = new CountDownLatch(1);
// Make sure all threads are finished ; private static final CountDownLatch threadSemaphore = new
CountDownLatch(THREAD_NUM); private static final Logger LOG =
LoggerFactory.getLogger(AllZooKeeperWatcher.class); public DistributedLock(int
id) { this.threadId = id; LOG_PREFIX_OF_THREAD = "【 The first "+threadId+" Threads 】"; } public
static void main(String[] args) { for(int i=0; i < THREAD_NUM; i++){ final int
threadId = i+1; new Thread(){ @Override public void run() { try{
DistributedLock dc = new DistributedLock(threadId);
dc.createConnection(CONNECTION_STRING, SESSION_TIMEOUT);
//GROUP_PATH If it doesn't exist , Created by one thread ; //synchronized (threadSemaphore){
dc.createPath(GROUP_PATH, " This node is supported by a thread " + threadId + " establish ", true); //} dc.getLock();
} catch (Exception e){ LOG.error("【 The first "+threadId+" Threads 】 Exception thrown :");
e.printStackTrace(); } } }.start(); } try { threadSemaphore.await();
LOG.info(" End of all threads !"); } catch (InterruptedException e) { e.printStackTrace();
} } /** * Acquire lock * @return */ private void getLock() throws KeeperException,
InterruptedException { selfPath = zk.create(SUB_PATH,null,
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
LOG.info(LOG_PREFIX_OF_THREAD+" Create lock path :"+selfPath); if(checkMinPath()){
getLockSuccess(); } } /** * Create node * @param path node path * @param data Initial data content *
@return */ public boolean createPath( String path, String data, boolean
needWatch) throws KeeperException, InterruptedException { if(zk.exists(path,
needWatch)==null){ LOG.info( LOG_PREFIX_OF_THREAD + " Node created successfully , Path: " +
this.zk.create( path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT ) + ", content: " + data ); } return true; } /** * establish ZK connect
* @param connectString ZK Server address list * @param sessionTimeout Session Timeout */ public
void createConnection( String connectString, int sessionTimeout ) throws
IOException, InterruptedException { zk = new ZooKeeper( connectString,
sessionTimeout, this); connectedSemaphore.await(); } /** * Lock acquired successfully */ public void
getLockSuccess() throws KeeperException, InterruptedException {
if(zk.exists(this.selfPath,false) == null){
LOG.error(LOG_PREFIX_OF_THREAD+" This node is no longer available ..."); return; }
LOG.info(LOG_PREFIX_OF_THREAD + " Lock acquired successfully , Hurry to work !"); Thread.sleep(2000);
LOG.info(LOG_PREFIX_OF_THREAD + " Delete this node :"+selfPath); zk.delete(this.selfPath,
-1); releaseConnection(); threadSemaphore.countDown(); } /** * close ZK connect */ public
void releaseConnection() { if ( this.zk !=null ) { try { this.zk.close(); }
catch ( InterruptedException e ) {} } LOG.info(LOG_PREFIX_OF_THREAD + " Release connection ");
} /** * Check if you are the smallest node * @return */ public boolean checkMinPath() throws
KeeperException, InterruptedException { List<String> subNodes =
zk.getChildren(GROUP_PATH, false); Collections.sort(subNodes); int index =
subNodes.indexOf( selfPath.substring(GROUP_PATH.length()+1)); switch (index){
case -1:{ LOG.error(LOG_PREFIX_OF_THREAD+" This node is no longer available ..."+selfPath); return false;
} case 0:{ LOG.info(LOG_PREFIX_OF_THREAD+" In child nodes , I'm the boss "+selfPath); return true;
} default:{ this.waitPath = GROUP_PATH +"/"+ subNodes.get(index - 1);
LOG.info(LOG_PREFIX_OF_THREAD+" Get child nodes , In front of me "+waitPath); try{
zk.getData(waitPath, true, new Stat()); return false; }catch(KeeperException
e){ if(zk.exists(waitPath,false) == null){
LOG.info(LOG_PREFIX_OF_THREAD+" In child nodes , In front of me "+waitPath+" Disappeared , Happiness comes too suddenly ?"); return
checkMinPath(); }else{ throw e; } } } } } @Override public void
process(WatchedEvent event) { if(event == null){ return; } Event.KeeperState
keeperState = event.getState(); Event.EventType eventType = event.getType(); if
( Event.KeeperState.SyncConnected == keeperState) { if ( Event.EventType.None
== eventType ) { LOG.info( LOG_PREFIX_OF_THREAD + " Successfully connected to ZK The server " );
connectedSemaphore.countDown(); }else if (event.getType() ==
Event.EventType.NodeDeleted && event.getPath().equals(waitPath)) {
LOG.info(LOG_PREFIX_OF_THREAD + " Receive information , The guy in front of me is up , Can I come out of the mountain ?"); try {
if(checkMinPath()){ getLockSuccess(); } } catch (KeeperException e) {
e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); }
} }else if ( Event.KeeperState.Disconnected == keeperState ) { LOG.info(
LOG_PREFIX_OF_THREAD + " And ZK Server Disconnected " ); } else if ( Event.KeeperState.AuthFailed
== keeperState ) { LOG.info( LOG_PREFIX_OF_THREAD + " Permission check failed " ); } else if (
Event.KeeperState.Expired == keeperState ) { LOG.info( LOG_PREFIX_OF_THREAD +
" Session failure " ); } } }
log configuration file :# DEFAULT log4j.rootLogger=INFO,CONSOLE # # Log INFO level and above
messages to the console #
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} - %m%n
log4j.appender.COMMONSTAT=org.apache.log4j.DailyRollingFileAppender
log4j.appender.COMMONSTAT.Threshold=INFO
log4j.appender.COMMONSTAT.File=/home/zookeeper/zookeeper-test-agent/logs/test.log
log4j.appender.COMMONSTAT.DatePattern='.'yyyy-MM-dd
log4j.appender.COMMONSTAT.layout=org.apache.log4j.PatternLayout
log4j.appender.COMMONSTAT.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] -
%m%n log4j.logger.org.displaytag=WARN log4j.logger.org.apache.zookeeper=ERROR
log4j.logger.org.springframework=WARN log4j.logger.org.I0Itec=WARN
log4j.logger.commonStat=INFO,COMMONSTAT
Operation results :2014-11-19 11:34:10,894 - 【 The first 9 Threads 】 Successfully connected to ZK The server 2014-11-19 11:34:10,895 -
【 The first 8 Threads 】 Successfully connected to ZK The server 2014-11-19 11:34:10,894 - 【 The first 1 Threads 】 Successfully connected to ZK The server 2014-11-19
11:34:10,894 - 【 The first 7 Threads 】 Successfully connected to ZK The server 2014-11-19 11:34:10,894 - 【 The first 4 Threads 】 Successfully connected to ZK The server
2014-11-19 11:34:10,895 - 【 The first 5 Threads 】 Successfully connected to ZK The server 2014-11-19 11:34:10,896 -
【 The first 2 Threads 】 Successfully connected to ZK The server 2014-11-19 11:34:10,894 - 【 The first 10 Threads 】 Successfully connected to ZK The server 2014-11-19
11:34:10,894 - 【 The first 3 Threads 】 Successfully connected to ZK The server 2014-11-19 11:34:10,895 - 【 The first 6 Threads 】 Successfully connected to ZK The server
2014-11-19 11:34:10,910 - 【 The first 9 Threads 】 Node created successfully , Path: /disLocks, content: This node is supported by a thread 9 establish
2014-11-19 11:34:10,912 - 【 The first 9 Threads 】 Create lock path :/disLocks/sub0000000000 2014-11-19
11:34:10,917 - 【 The first 6 Threads 】 Create lock path :/disLocks/sub0000000001 2014-11-19 11:34:10,917 -
【 The first 9 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000000 2014-11-19 11:34:10,921 -
【 The first 3 Threads 】 Create lock path :/disLocks/sub0000000002 2014-11-19 11:34:10,922 -
【 The first 6 Threads 】 Get child nodes , In front of me /disLocks/sub0000000000 2014-11-19 11:34:10,923 -
【 The first 9 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:10,924 -
【 The first 10 Threads 】 Create lock path :/disLocks/sub0000000003 2014-11-19 11:34:10,924 -
【 The first 3 Threads 】 Get child nodes , In front of me /disLocks/sub0000000001 2014-11-19 11:34:10,928 -
【 The first 10 Threads 】 Get child nodes , In front of me /disLocks/sub0000000002 2014-11-19 11:34:10,929 -
【 The first 1 Threads 】 Create lock path :/disLocks/sub0000000004 2014-11-19 11:34:10,932 -
【 The first 5 Threads 】 Create lock path :/disLocks/sub0000000005 2014-11-19 11:34:10,935 -
【 The first 1 Threads 】 Get child nodes , In front of me /disLocks/sub0000000003 2014-11-19 11:34:10,936 -
【 The first 2 Threads 】 Create lock path :/disLocks/sub0000000006 2014-11-19 11:34:10,936 -
【 The first 5 Threads 】 Get child nodes , In front of me /disLocks/sub0000000004 2014-11-19 11:34:10,940 -
【 The first 4 Threads 】 Create lock path :/disLocks/sub0000000007 2014-11-19 11:34:10,941 -
【 The first 2 Threads 】 Get child nodes , In front of me /disLocks/sub0000000005 2014-11-19 11:34:10,943 -
【 The first 8 Threads 】 Create lock path :/disLocks/sub0000000008 2014-11-19 11:34:10,944 -
【 The first 4 Threads 】 Get child nodes , In front of me /disLocks/sub0000000006 2014-11-19 11:34:10,945 -
【 The first 7 Threads 】 Create lock path :/disLocks/sub0000000009 2014-11-19 11:34:10,946 -
【 The first 8 Threads 】 Get child nodes , In front of me /disLocks/sub0000000007 2014-11-19 11:34:10,947 -
【 The first 7 Threads 】 Get child nodes , In front of me /disLocks/sub0000000008 2014-11-19 11:34:12,923 -
【 The first 9 Threads 】 Delete this node :/disLocks/sub0000000000 2014-11-19 11:34:12,926 -
【 The first 6 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:12,928 -
【 The first 6 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000001 2014-11-19 11:34:12,930 - 【 The first 9 Threads 】 Release connection
2014-11-19 11:34:12,930 - 【 The first 6 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:14,930 -
【 The first 6 Threads 】 Delete this node :/disLocks/sub0000000001 2014-11-19 11:34:14,937 -
【 The first 3 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:14,941 -
【 The first 3 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000002 2014-11-19 11:34:14,943 - 【 The first 6 Threads 】 Release connection
2014-11-19 11:34:14,946 - 【 The first 3 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:16,946 -
【 The first 3 Threads 】 Delete this node :/disLocks/sub0000000002 2014-11-19 11:34:16,949 -
【 The first 10 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:16,951 -
【 The first 10 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000003 2014-11-19 11:34:16,953 -
【 The first 3 Threads 】 Release connection 2014-11-19 11:34:16,953 - 【 The first 10 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19
11:34:18,953 - 【 The first 10 Threads 】 Delete this node :/disLocks/sub0000000003 2014-11-19 11:34:18,957 -
【 The first 1 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:18,960 - 【 The first 10 Threads 】 Release connection
2014-11-19 11:34:18,961 - 【 The first 1 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000004 2014-11-19
11:34:18,964 - 【 The first 1 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:20,964 -
【 The first 1 Threads 】 Delete this node :/disLocks/sub0000000004 2014-11-19 11:34:20,967 -
【 The first 5 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:20,969 -
【 The first 5 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000005 2014-11-19 11:34:20,971 - 【 The first 1 Threads 】 Release connection
2014-11-19 11:34:20,971 - 【 The first 5 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:22,971 -
【 The first 5 Threads 】 Delete this node :/disLocks/sub0000000005 2014-11-19 11:34:22,974 -
【 The first 2 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:22,978 -
【 The first 2 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000006 2014-11-19 11:34:22,979 - 【 The first 5 Threads 】 Release connection
2014-11-19 11:34:22,981 - 【 The first 2 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:24,981 -
【 The first 2 Threads 】 Delete this node :/disLocks/sub0000000006 2014-11-19 11:34:24,985 -
【 The first 4 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:24,989 - 【 The first 2 Threads 】 Release connection
2014-11-19 11:34:24,989 - 【 The first 4 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000007 2014-11-19
11:34:24,995 - 【 The first 4 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:26,995 -
【 The first 4 Threads 】 Delete this node :/disLocks/sub0000000007 2014-11-19 11:34:26,998 -
【 The first 8 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:27,000 -
【 The first 8 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000008 2014-11-19 11:34:27,004 -
【 The first 8 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:27,004 - 【 The first 4 Threads 】 Release connection 2014-11-19
11:34:29,004 - 【 The first 8 Threads 】 Delete this node :/disLocks/sub0000000008 2014-11-19 11:34:29,007 -
【 The first 7 Threads 】 Receive information , The guy in front of me is up , Can I come out of the mountain ? 2014-11-19 11:34:29,009 -
【 The first 7 Threads 】 In child nodes , I'm the boss /disLocks/sub0000000009 2014-11-19 11:34:29,010 - 【 The first 8 Threads 】 Release connection
2014-11-19 11:34:29,011 - 【 The first 7 Threads 】 Lock acquired successfully , Hurry to work ! 2014-11-19 11:34:31,011 -
【 The first 7 Threads 】 Delete this node :/disLocks/sub0000000009 2014-11-19 11:34:31,017 - 【 The first 7 Threads 】 Release connection
2014-11-19 11:34:31,017 - End of all threads !

Technology
©2019-2020 Toolsou All rights reserved,
Python Basic knowledge and notes 2021 year 1 Monthly programmer salary statistics , average 14915 element GDOI2019 travels C++ Standard library What should I do if I suddenly encounter a question I can't answer during the interview ?2021 year 2 Monthly programmer salary statistics , average 15144 element college examination for the self-taught An overview of Marxism use C++ I want to talk to you “ Prototype mode ” ( copy / copy constructor ) How to use it quickly html and css Write static page Bitcoin in ten years ,VDS Opportunity or fraud