refactor(性能测试): 同步各个节点的启动时间
This commit is contained in:
parent
26d7a007a8
commit
295fccf120
|
@ -0,0 +1,169 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* A Weak Concurrent Hash Map Solution which stores the keys and values only for a specific amount of time, and then expires after that
|
||||
* time.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* // Create a Map Object
|
||||
* long expiryInMillis = 1 * 60 * 1000; // 1 minute
|
||||
* io.metersphere.commons.utils.WeakConcurrentHashMap<String, Object> map = new io.metersphere.commons.utils.WeakConcurrentHashMap<String, Object>(expiryInMillis);
|
||||
*
|
||||
* // Use it
|
||||
* map.put("key", valueObject);
|
||||
* Object valueObject = map.get("key");
|
||||
*
|
||||
* // quit using it
|
||||
* map.quitMap();
|
||||
* </pre>
|
||||
* <p>
|
||||
* And to check if the map is alive
|
||||
*
|
||||
* <pre>
|
||||
* if (map.isAlive()) {
|
||||
* // Your operations on map
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param <K>
|
||||
* @param <V>
|
||||
* @author Vivekananthan M
|
||||
*/
|
||||
public class WeakConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Map<K, Long> timeMap = new ConcurrentHashMap<K, Long>();
|
||||
private WeakConcurrentHashMapListener<K, V> listener;
|
||||
private long expiryInMillis;
|
||||
private boolean mapAlive = true;
|
||||
|
||||
public WeakConcurrentHashMap() {
|
||||
this.expiryInMillis = 10000;
|
||||
initialize();
|
||||
}
|
||||
|
||||
public WeakConcurrentHashMap(WeakConcurrentHashMapListener<K, V> listener) {
|
||||
this.listener = listener;
|
||||
this.expiryInMillis = 10000;
|
||||
initialize();
|
||||
}
|
||||
|
||||
public WeakConcurrentHashMap(long expiryInMillis) {
|
||||
this.expiryInMillis = expiryInMillis;
|
||||
initialize();
|
||||
}
|
||||
|
||||
public WeakConcurrentHashMap(long expiryInMillis, WeakConcurrentHashMapListener<K, V> listener) {
|
||||
this.expiryInMillis = expiryInMillis;
|
||||
this.listener = listener;
|
||||
initialize();
|
||||
}
|
||||
|
||||
void initialize() {
|
||||
new CleanerThread().start();
|
||||
}
|
||||
|
||||
public void registerRemovalListener(WeakConcurrentHashMapListener<K, V> listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException if trying to insert values into map after quiting
|
||||
*/
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
if (!mapAlive) {
|
||||
throw new IllegalStateException("WeakConcurrent Hashmap is no more alive.. Try creating a new one."); // No I18N
|
||||
}
|
||||
Date date = new Date();
|
||||
timeMap.put(key, date.getTime());
|
||||
V returnVal = super.put(key, value);
|
||||
if (listener != null) {
|
||||
listener.notifyOnAdd(key, value);
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException if trying to insert values into map after quiting
|
||||
*/
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
if (!mapAlive) {
|
||||
throw new IllegalStateException("WeakConcurrent Hashmap is no more alive.. Try creating a new one."); // No I18N
|
||||
}
|
||||
for (K key : m.keySet()) {
|
||||
put(key, m.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException if trying to insert values into map after quiting
|
||||
*/
|
||||
@Override
|
||||
public V putIfAbsent(K key, V value) {
|
||||
if (!mapAlive) {
|
||||
throw new IllegalStateException("WeakConcurrent Hashmap is no more alive.. Try creating a new one."); // No I18N
|
||||
}
|
||||
if (!containsKey(key)) {
|
||||
return put(key, value);
|
||||
} else {
|
||||
return get(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should call this method when it's no longer required
|
||||
*/
|
||||
public void quitMap() {
|
||||
mapAlive = false;
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return mapAlive;
|
||||
}
|
||||
|
||||
/**
|
||||
* This thread performs the cleaning operation on the concurrent hashmap once in a specified interval. This wait interval is half of the
|
||||
* time from the expiry time.
|
||||
*/
|
||||
class CleanerThread extends Thread {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (mapAlive) {
|
||||
cleanMap();
|
||||
try {
|
||||
Thread.sleep(expiryInMillis / 2);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanMap() {
|
||||
long currentTime = new Date().getTime();
|
||||
for (K key : timeMap.keySet()) {
|
||||
if (currentTime > (timeMap.get(key) + expiryInMillis)) {
|
||||
V value = remove(key);
|
||||
timeMap.remove(key);
|
||||
if (listener != null) {
|
||||
listener.notifyOnRemoval(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
public interface WeakConcurrentHashMapListener<K, V> {
|
||||
public void notifyOnAdd(K key, V value);
|
||||
|
||||
public void notifyOnRemoval(K key, V value);
|
||||
}
|
Loading…
Reference in New Issue