Синхронизация с использованием повторной блокировки запросов к базе данных в многопоточном приложении java - PullRequest
0 голосов
/ 29 мая 2020

Итак, я разрабатываю многопоточную систему, которая отправляет команды (шаблон разработки команд) от клиента к серверу, и там они выполняются java.util.concurrent.newCachedThreadPool, а ответ отправляется обратно с использованием UDP.

Внутри этой команды мне нужно обработать некоторые запросы к базе данных и изменения в локальной java.util.HashMap коллекции. Вся синхронизация должна производиться с использованием java.util.concurrent.locks.ReentrantLock.

Запросы простые, INSERT, DELETE, UPDATE, с использованием идентификатора автоинкремента и обычных данных. Для транзакций я использую java.sql.PreparedState и обычный java.sql.Connection шаблон фиксации, et c.

Для связи с базой данных у меня есть 3 класса:

  • UserModel, имеет все запросы, связанные с управлением пользователями
  • CollectionModel, все запросы, относящиеся к коллекции
  • CollectionController, имеет экземпляр моделей и вызывает их методы, чтобы упростить задачу команды для выполнения вызовов и изменений db.

И в зависимости от результата запросов я меняю локальную коллекцию. Теперь мои вопросы следующие:

  1. Как реализовать ReentrantLock для синхронизации изменений, сделанных в локальной коллекции.
  2. ReentrantLock должен быть реализован на уровне CollectionController или должна быть блокировка внутри каждой модели
  3. Действительно ли необходимо реализовать синхронизированную среду для вызова и изменений базы данных? Важно отметить, что я использую шаблон транзакции для каждого запроса.
  4. Как будет реализована блокировка на уровне моделей?
  5. Я открыт для изменений в структуре проект, чтобы сделать его более solid на многопоточном. В специальной части Executor я не совсем уверен, правильно ли это реализовать.

CollectionManager. java, home of В локальной коллекции методы вызываются в зависимости от команды и ее метода execute ().

public class CollectionManager {
    private HashMap<Integer, Dragon> collection = new HashMap<Integer, Dragon>;

    public void clear() {
        this.getCollection().clear();
    }

    /**
     * Функция сортировки коллекции
     * @return возвращает отсортированную по ID коллекцию
     */
    public List<ListEntrySerializable> sortById()
    {

        return this.getCollection()
                .entrySet()
                .stream()
                .sorted(Comparator.comparing(x -> x.getValue().getId()))
                .map(e -> new ListEntrySerializable(e.getKey(), e.getValue()))
                .collect(Collectors.toList());
    }

    public Object insert(Integer key, Dragon newDragon) {
        return this.getCollection().putIfAbsent(key, newDragon);
    }

    public Object update(Integer id, Dragon newDragon)
    {
        Optional<Map.Entry<Integer, Dragon>> oldDragonKey =
                this.getCollection()
                .entrySet()
                .stream()
                .filter(dragonEntry -> dragonEntry.getValue().getId().equals(id))
                .findFirst();

        if (oldDragonKey.isPresent())
            newDragon.setId(id);

        return oldDragonKey.map(integerDragonEntry ->
                this.getCollection().replace(integerDragonEntry.getKey(), newDragon)).orElse(null);
    }

    public Object removeKey(Integer key){
        return this.getCollection().remove(key);
    }

Метод-исполнитель для выполнения команды отправляет каждый ответ с сервера

private void executeObj(Object obj, SocketAddress addressFromClient) {
        Future<Object> resulted = executor.submit(() -> {
            Object responseExecution;
            if (obj instanceof String)
                responseExecution = obj;
            else {
                AbsCommand command = ((CommandPacket) obj).getCommand();
                Credentials credentials = ((CommandPacket) obj).getCredentials();
                try {
                    responseExecution = command.execute(executionContext, credentials);
                }catch (Exception ex) {
                    responseExecution = ex.getMessage();
                    LOG.error(ex.getMessage(), ex);
                }
            }
            socket.sendResponse(responseExecution, addressFromClient);
            return responseExecution;
        });

     //....method to print the future object (not important)
    }

...