如何在静态列表中捕获请求数据
How can I capture request data in a static list
我有一个 URL 例如:
http://some_url.suffix?data=test1.
我将收到多个此类请求:
http://some_url.suffix?data=test1
http://some_url.suffix?data=test2
http://some_url.suffix?data=test3
http://some_url.suffix?data=test4
我想在服务器端维护一个静态列表,其中包含从所有会话的请求中收到的数据
List<String> data;
列表将包含数据 1、数据 2、数据 3、数据 4。列表将在特定时间间隔后被清除,新列表将用于后续请求。
实现此目标的最佳选择是什么:
1. static List<String> data = new CopyOnWriteArrayList<String>();
2. Singleton wrapper class to perform operation on normal java.util.List
3. using synchronized block
我会使用带有方法的单例服务
public boolean addKey(String key, String value);
然后在您的服务中我会使用 HashMap>
private static Map<String, List<String>> keysMap;
private Map<String, List<String>> getKeysMap(){
synchronized (this){
if(keysMap == null){
keysMap = new HashMap();
}
return keysMap;
}
}
public void addKey(String key, String value){
List<String> keyParams = getKeysMap().get(key);
if(keyParams == null){
keyParams = new ArrayList();
}
//decide here if you want to store repeated values
keyParams.add(param);
getKeysMap().put(key, keyParams);
}
第一个解决方案可能会导致性能问题,因为每个传入请求都会复制数组。
第三个解决方案更好,请记住内在锁也应该是 controller/service 上的静态对象。这也需要在每次触摸 data
时记住同步块,所以这可能也不是最佳解决方案。
在我看来,第二个选项是该案例的最佳解决方案。创建内部存储 data
的单例并提供 synchronized
方法来使用它。同步内容将在 class.
内关闭
我尝试实现该单例包装器如下所示:
//Use enum to have singleton provided by jvm
enum DataCache {
INSTANCE;
//Use LinkedList if you expecting many calls. The insertion will be much faster.
private List<String> data = new LinkedList<>();
synchronized void add(String value) {
data.add(value);
}
/*
* Returns defensive copy, so that no one has reference to this.data.
* If data is fetched only on clear you can make this private instead of synchronized
* (or even better get rid of it and create defensive copy inside clear()).
*/
synchronized List<String> get() {
return new ArrayList<>(data);
}
/*
* Returns last snapshot of data to keep consistency.
*/
synchronized List<String> clear() {
List<String> lastSnapshot = get();
data = new LinkedList<>();
return lastSnapshot;
}
}
然后你可以在处理请求的方法中使用INSTANCE.add()
,在调度程序中使用INSTANCE.clear()
。
注意我不知道你如何处理收集到的数据,但请考虑列表以外的其他集合。如果特定数据出现的次数不重要,最好将 List
替换为 Set
和 HashSet
实现。 (比如当你收到两次 data=test1
并且你只关心 test1 来了多少次)。如果您关心数字,您还可以考虑将值映射到出现次数。
我有一个 URL 例如:
http://some_url.suffix?data=test1.
我将收到多个此类请求:
http://some_url.suffix?data=test1
http://some_url.suffix?data=test2
http://some_url.suffix?data=test3
http://some_url.suffix?data=test4
我想在服务器端维护一个静态列表,其中包含从所有会话的请求中收到的数据
List<String> data;
列表将包含数据 1、数据 2、数据 3、数据 4。列表将在特定时间间隔后被清除,新列表将用于后续请求。 实现此目标的最佳选择是什么:
1. static List<String> data = new CopyOnWriteArrayList<String>();
2. Singleton wrapper class to perform operation on normal java.util.List
3. using synchronized block
我会使用带有方法的单例服务
public boolean addKey(String key, String value);
然后在您的服务中我会使用 HashMap>
private static Map<String, List<String>> keysMap;
private Map<String, List<String>> getKeysMap(){
synchronized (this){
if(keysMap == null){
keysMap = new HashMap();
}
return keysMap;
}
}
public void addKey(String key, String value){
List<String> keyParams = getKeysMap().get(key);
if(keyParams == null){
keyParams = new ArrayList();
}
//decide here if you want to store repeated values
keyParams.add(param);
getKeysMap().put(key, keyParams);
}
第一个解决方案可能会导致性能问题,因为每个传入请求都会复制数组。
第三个解决方案更好,请记住内在锁也应该是 controller/service 上的静态对象。这也需要在每次触摸 data
时记住同步块,所以这可能也不是最佳解决方案。
在我看来,第二个选项是该案例的最佳解决方案。创建内部存储 data
的单例并提供 synchronized
方法来使用它。同步内容将在 class.
我尝试实现该单例包装器如下所示:
//Use enum to have singleton provided by jvm
enum DataCache {
INSTANCE;
//Use LinkedList if you expecting many calls. The insertion will be much faster.
private List<String> data = new LinkedList<>();
synchronized void add(String value) {
data.add(value);
}
/*
* Returns defensive copy, so that no one has reference to this.data.
* If data is fetched only on clear you can make this private instead of synchronized
* (or even better get rid of it and create defensive copy inside clear()).
*/
synchronized List<String> get() {
return new ArrayList<>(data);
}
/*
* Returns last snapshot of data to keep consistency.
*/
synchronized List<String> clear() {
List<String> lastSnapshot = get();
data = new LinkedList<>();
return lastSnapshot;
}
}
然后你可以在处理请求的方法中使用INSTANCE.add()
,在调度程序中使用INSTANCE.clear()
。
注意我不知道你如何处理收集到的数据,但请考虑列表以外的其他集合。如果特定数据出现的次数不重要,最好将 List
替换为 Set
和 HashSet
实现。 (比如当你收到两次 data=test1
并且你只关心 test1 来了多少次)。如果您关心数字,您还可以考虑将值映射到出现次数。