利用Zookeeper臨時(shí)節(jié)點(diǎn)(客戶端異常斷開連接后臨時(shí)節(jié)點(diǎn)自動(dòng)移除)或者Redis SETNX(set if not exists)(設(shè)置ttl)可以實(shí)現(xiàn)分布式鎖,這里先利用zk實(shí)現(xiàn)一個(gè)
?
import org.I0Itec.zkclient.ZkClient;import java.util.concurrent.CountDownLatch;public class ZKDistributeLockTest { public static void main(String[] args) { // 使用CountDownLunch控制線程同時(shí)執(zhí)行 CountDownLatch countDownLatch = new CountDownLatch(1); // 開啟3個(gè)線程模擬分布式環(huán)境,分布式環(huán)境下每個(gè)進(jìn)程都是一個(gè)單獨(dú)的zkClient Thread t1 = new Thread(new TestThread(countDownLatch)); Thread t2 = new Thread(new TestThread(countDownLatch)); Thread t3 = new Thread(new TestThread(countDownLatch)); t1.start(); t2.start(); t3.start(); System.out.println("休眠1秒后執(zhí)行..." System.currentTimeMillis()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 倒計(jì)時(shí)結(jié)束 countDownLatch.countDown(); }}// 線程,嘗試在zk上創(chuàng)建臨時(shí)節(jié)點(diǎn),創(chuàng)建成功則獲得鎖(執(zhí)行權(quán))class TestThread implements Runnable { // 共享變量 private static Integer CNT = 0; private ZkClient zkClient; private CountDownLatch countDownLatch; public TestThread(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } // 連接zk private void connect() { String threadName = Thread.currentThread().getName(); try { System.out.println(threadName " 等待執(zhí)行..."); // 等待倒計(jì)時(shí)結(jié)束 countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName " 請(qǐng)求連接zk..." System.currentTimeMillis()); zkClient = new ZkClient("192.168.1.217:2181", 20000); System.out.println(threadName " 連接成功..."); // 輸出目錄信息測(cè)試// List<String> children = zkClient.getChildren("/");// children.forEach(System.out::println); } @Override public void run() { // 初始化連接(在各個(gè)線程里開啟連接,模擬分布式環(huán)境) connect(); String threadName = Thread.currentThread().getName(); // 競爭鎖 while (true) { try { System.out.println(threadName " 開始競爭鎖..."); // 創(chuàng)建zk臨時(shí)節(jié)點(diǎn) zkClient.createEphemeral("/dl", "test"); System.out.println(threadName " 獲得鎖?。?!"); // 獲得鎖后修改共享變量 CNT ; System.out.println(threadName " 釋放了鎖..." CNT); zkClient.delete("/dl"); Thread.sleep(2000); } catch (Exception e) { // 創(chuàng)建臨時(shí)節(jié)點(diǎn)失敗,表示未獲得鎖 System.out.println(threadName " 未獲得鎖,將重試!?。?);// System.out.println(e.getMessage()); try { Thread.sleep(1500); } catch (InterruptedException e1) { e1.printStackTrace(); } } } }}
?
來源:https://www.icode9.com/content-4-339151.html聯(lián)系客服