#java #volatile #data-synchronization
Вопрос:
Моя Java-программа запрашивает API клиента, и API клиента возвращает пару ключ-значение через нерегулярные промежутки времени (т. Е. не каждые 5 секунд / 10 секунд, иногда 1 секунду или 5 секунд).
И я вставил свой собственный код , который является a HashMap
, в код API клиента для хранения всех пар ключ-значение.
Моя цель-запустить приведенный ниже код с пометкой»!!!», как только будут выполнены условия хэш-карты. Я не эксперт в синхронизации данных Java. Обратите внимание, что Thread.Sleep(3000)
это не сработает, так как пары ключ-значение обновляются с нерегулярными интервалами времени. Более того, значение одного и того же ключа также будет меняться с течением времени. Я попробовал запустить программу ниже, и она сразу же пробежала блок кода, помеченный»!!!», чего я не хочу достичь.
Каково наиболее эффективное решение этой проблемы ?
Class Testing{
public static void main(String[] args){
// connect to API...
ClientAPI clientAPI = new ClientAPI();
clientAPI.connect();
// make a request to retrieve an update of a HashMap
clientAPI.requestHashMapUpdate();
// !!! execute the following block of code only if hashmap contains a specific key value pair, i.e. key1, 1
// if hashmap does not contain key or the key-value pair do not match , then wait until the key-value pair are matched and run the code
if(clientAPI.getMyHashMap().containsKey("key1")){
if(clientAPI.getMyHashMap().get("key1") == 1){
System.out.println("Print Me only if key and value are matched !!!!!!!!");
}
}
}
}
Class ClientAPI{
private HashMap<String,Integer> myHashMap;
// Constructor
public clientAPI(){
myHashMap = new HashMap<String,Integer>();
}
// callback function of API's requestHashMapUpdate method
public void updateHashMapKeyValuePair(String key, int value){
System.out.println("Key:" key ", Value: " value);
// code i wrote to update hashmap with key value pair returned from API
myHashMap.put(key,value);
}
// my code to retrieve the latest snapshot of myHashMap
public HashMap<String,Integer> getMyHashMap(){
return myHashMap;
}
}
Комментарии:
1. На самом деле вы мало что можете сделать, кроме как проверять содержимое хэш-карты каждый раз, когда она обновляется. Если вы не можете получать уведомления о его обновлении, на самом деле вы мало что можете сделать, кроме опроса.
2. Есть ли способ уведомить программу о том, когда хэш-карта обновляется?
3. Не по своей сути. Просто уведомьте клиентов из кода, в котором вы обновляете карту.
Ответ №1:
Переопределите свой клиентский API (если он не закрыт для расширения):
class MyClientAPI extends ClientAPI {
...
@Override
public void updateHashMapKeyValuePair(String key, int value) {
super.updateHashMapKeyValuePair(key, value);
if("key1".equals(key) amp;amp; 1 == value)
System.out.println("Print Me only if key and value are matched !!!!!!!!");
}
...
}
и просто проверяйте каждое новое поступающее значение.
Чтобы использовать его, только измените
ClientAPI clientAPI = new MyClientAPI();
Другой способ решить эту проблему-предоставить вашему ClientAPI
классу возможность регистрировать слушателей
interface UpdateHashMapKeyValuePairListener {
void digestUpdate(String key, int value);
}
class ClientAPI {
...
private List<UpdateHashMapKeyValuePairListener> listeners = new ArrayList();
...
public void registerUpdateListener(UpdateHashMapKeyValuePairListener u) {
listeners.add(u);
}
...
public void updateHashMapKeyValuePair(final String key, final int value) {
listeners.forEach(u -> u.digestUpdate(key, value));
...
}
...
}
затем любой, кто хочет знать, когда вводится новое значение, просто реализует этот интерфейс, например
...
clientAPI.registerUpdateListener((key, value) -> {
if("key1".equals(key) amp;amp; 1 == value)
System.out.println("Print Me only if key and value are matched !!!!!!!!");
});
clientAPI.connect();
...
Ответ №2:
Проверяйте содержимое хэш-карты каждый раз, когда она обновляется. Для достижения этой цели вы можете зарегистрировать прослушиватель в Testing
классе, который будет запускаться каждый раз HashMap
, когда он обновляется в ClientAPI
классе.
Сначала определите функциональный интерфейс для слушателя:
@FunctionalInterface
public interface OnUpdateMapListener {
void onUpdateMap(Map<String, Integer> map);
}
затем добавьте слушателя в ClientAPI
public class ClientAPI {
private HashMap<String, Integer> myHashMap;
private OnUpdateMapListener onUpdateMapListener;
Определите onMapUpdate
метод для передачи тела слушателя в ClientAPI
:
public void onMapUpdate(OnUpdateMapListener onUpdateMapListener) {
this.onUpdateMapListener = onUpdateMapListener;
}
и вызвать прослушиватель при обновлении хэш-карты в updateHashMapKeyValuePair
public void updateHashMapKeyValuePair(String key, int value) {
System.out.println("Key:" key ", Value: " value);
// code i wrote to update hashmap with key value pair returned from API
myHashMap.put(key, value);
onUpdateMapListener.onUpdateMap(myHashMap);
}
В основном методе зарегистрируйте слушателя и проверьте содержимое карты. Это будет срабатывать каждый раз ClientAPI
, когда метод получает новое содержимое карты updateHashMapKeyValuePair
:
clientAPI.onMapUpdate(stringIntegerHashMap -> {
// !!! the following code is executed every time the hashMap is updated
if (clientAPI.getMyHashMap().containsKey("key1")) {
if (clientAPI.getMyHashMap().get("key1") == 1) {
System.out.println("Print Me only if key and value are matched !!!!!!!!");
}
}
});
ClientAPI
класс:
public class ClientAPI {
private HashMap<String, Integer> myHashMap;
private OnUpdateMapListener onUpdateMapListener;
// Constructor
public ClientAPI() {
myHashMap = new HashMap<String, Integer>();
}
// callback function of API's requestHashMapUpdate method
public void updateHashMapKeyValuePair(String key, int value) {
System.out.println("Key:" key ", Value: " value);
// code i wrote to update hashmap with key value pair returned from API
myHashMap.put(key, value);
onUpdateMapListener.onUpdateMap(myHashMap);
}
// my code to retrieve the latest snapshot of myHashMap
public HashMap<String, Integer> getMyHashMap() {
return myHashMap;
}
public void requestHashMapUpdate() {
//.....
}
public void onMapUpdate(OnUpdateMapListener onUpdateMapListener) {
this.onUpdateMapListener = onUpdateMapListener;
}
}
Testing
класс:
public static void main(String[] args) {
// connect to API...
ClientAPI clientAPI = new ClientAPI();
clientAPI.connect();
// make a request to retrieve an update of a HashMap
clientAPI.requestHashMapUpdate();
clientAPI.onMapUpdate(stringIntegerHashMap -> {
// !!! the following code is executed every time the hashMap is updated
if (clientAPI.getMyHashMap().containsKey("key1")) {
if (clientAPI.getMyHashMap().get("key1") == 1) {
System.out.println("Print Me only if key and value are matched !!!!!!!!");
}
}
});
clientAPI.updateHashMapKeyValuePair("key1", 1);
clientAPI.updateHashMapKeyValuePair("key1", 2);
}
Результаты:
Key:key1, Value: 1
Print Me only if key and value are matched !!!!!!!!
Key:key1, Value: 2