|
@@ -0,0 +1,246 @@
|
|
|
+package com.qmth.teachcloud.mark.utils;
|
|
|
+
|
|
|
+import com.qmth.teachcloud.common.util.DateDisposeUtils;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 链表模式实现的任务互斥锁工具
|
|
|
+ */
|
|
|
+public class TaskLock {
|
|
|
+
|
|
|
+ // 固定头节点
|
|
|
+ private LockNode head;
|
|
|
+
|
|
|
+ // 总量计数
|
|
|
+ private int count;
|
|
|
+
|
|
|
+ public TaskLock() {
|
|
|
+ head = new LockNode(0, 0, 0);
|
|
|
+ count = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized boolean add(Object id, int number, Object owner) {
|
|
|
+ if (head.next == null) {
|
|
|
+ head.append(id, number, owner);
|
|
|
+ count++;
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (true) {
|
|
|
+ // id+number,只能被一个owner获取
|
|
|
+ if (node.isId(id) && node.isNumber(number)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // id只能被一个owner领取一个number
|
|
|
+ else if (node.isId(id) && node.isOwner(owner)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 跳到下一个node
|
|
|
+ else if (node.hasNext()) {
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ // 可以领取
|
|
|
+ else {
|
|
|
+ node.append(id, number, owner);
|
|
|
+ count++;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized boolean exist(Object id, int number, Object owner) {
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if (node.isId(id) && node.isNumber(number)) {
|
|
|
+ return node.isOwner(owner);
|
|
|
+ } else {
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized boolean remove(Object id, int number, Object owner) {
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if (node.isId(id) && node.isNumber(number)) {
|
|
|
+ if (node.isOwner(owner)) {
|
|
|
+ node.remove();
|
|
|
+ count--;
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized boolean remove(Object id, int number) {
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if (node.isId(id) && node.isNumber(number)) {
|
|
|
+ node.remove();
|
|
|
+ count--;
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized void clear() {
|
|
|
+ head.next = null;
|
|
|
+ count = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized void clear(Object owner) {
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if (node.isOwner(owner)) {
|
|
|
+ node.remove();
|
|
|
+ count--;
|
|
|
+ }
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized void expire(long expireTime) {
|
|
|
+ long current = System.currentTimeMillis();
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if ((current - node.time) > expireTime) {
|
|
|
+ node.remove();
|
|
|
+ count--;
|
|
|
+ }
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized boolean refresh(Object id, int number, Object owner) {
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if (node.isId(id) && node.isNumber(number) && node.isOwner(owner)) {
|
|
|
+ node.time = System.currentTimeMillis();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized void refresh(Object owner) {
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if (node.isOwner(owner)) {
|
|
|
+ node.time = System.currentTimeMillis();
|
|
|
+ }
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public int count() {
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int count(Object owner) {
|
|
|
+ int count = 0;
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ if (node.isOwner(owner)) {
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Map<String, Object>> list() {
|
|
|
+ List<Map<String, Object>> list = new LinkedList<>();
|
|
|
+ LockNode node = head.next;
|
|
|
+ while (node != null) {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("taskId", node.getId());
|
|
|
+ map.put("number", node.getNumber());
|
|
|
+ map.put("markerId", node.getOwner());
|
|
|
+ map.put("time", DateDisposeUtils.parseDateToStr(DateDisposeUtils.YYYY_MM_DD_HH_MM_SS, new Date(node.getTime())));
|
|
|
+ list.add(map);
|
|
|
+ node = node.next;
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class LockNode {
|
|
|
+
|
|
|
+ private LockNode previous;
|
|
|
+
|
|
|
+ private LockNode next;
|
|
|
+
|
|
|
+ private Object id;
|
|
|
+
|
|
|
+ private int number;
|
|
|
+
|
|
|
+ private Object owner;
|
|
|
+
|
|
|
+ private long time;
|
|
|
+
|
|
|
+ LockNode(Object id, int number, Object owner) {
|
|
|
+ this.id = id;
|
|
|
+ this.number = number;
|
|
|
+ this.owner = owner;
|
|
|
+ this.time = System.currentTimeMillis();
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean hasNext() {
|
|
|
+ return this.next != null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isId(Object id) {
|
|
|
+ return this.id.equals(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isNumber(int number) {
|
|
|
+ return this.number == number;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isOwner(Object owner) {
|
|
|
+ return this.owner.equals(owner);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void remove() {
|
|
|
+ this.previous.next = this.next;
|
|
|
+ if (this.next != null) {
|
|
|
+ this.next.previous = this.previous;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void append(Object id, int number, Object owner) {
|
|
|
+ LockNode node = new LockNode(id, number, owner);
|
|
|
+ this.next = node;
|
|
|
+ node.previous = this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Object getId() {
|
|
|
+ return id;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getNumber() {
|
|
|
+ return number;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Object getOwner() {
|
|
|
+ return owner;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getTime() {
|
|
|
+ return time;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|