Eclipse RAP Multi-client, но с одним серверным потоком

Я понимаю, как RAP создает области, имеют определенные потоки для каждого клиента и так далее. Я также понимаю, что область применения уникальна для нескольких клиентов, однако я не знаю, как получить доступ к этой конкретной области в виде одного потока.

Я хотел бы иметь серверную часть (с доступом к базам данных и тому подобному), которая является единичным выполнением, чтобы обеспечить глобальное знание всех транзакций и чтобы запросы от клиентов выполнялись последовательно, а не параллельно.

В настоящее время я обращаюсь к контексту приложения следующим образом из пользовательского интерфейса:

synchronized( MyServer.class ) {
    ApplicationContext appContext = RWT.getApplicationContext();

    MyServer myServer = (MyServer) appContext.getAttribute("myServer");
        if (myServer == null){
          myServer = new MyServer();
          appContext.setAttribute("myServer", myServer);
        }
    myServer.doSomething(RWTUtils.getSessionID());
}

Даже если я получу доступ к объекту myServer и инициирую запросы, выполнение все равно будет выполняться в потоке пользовательского интерфейса.

На данный момент единственный способ убедиться в том, что на моем сервере используется синхронизация следующим образом

public class MyServer {
    String text = "";

    public void doSomething(String string) {
        try {
            synchronized (this) {
                System.out.println("doSomething - start :" + string);
                text += "[" + string + "]";
                System.out.println("text: " + (text));
                Thread.sleep(10000);
                System.out.println("text: " + (text));
                System.out.println("doSomething - stop :" + string);
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Есть ли лучший способ не управлять синхронизацией потоков самостоятельно?

Любая помощь приветствуется

РЕДАКТИРОВАТЬ: Чтобы лучше объяснить себя, вот что я имею в виду. Либо я доверяю базе данных для правильной обработки нескольких запросов, и мне приходится также обрабатывать некоторые другие знания синхронизированным образом для обмена информацией между клиентами (пример A), или я нахожу решение, когда другой поток обрабатывает оба (пример B), знания и база данных. Конечно, проблема здесь в том, что один клиент может блокировать других, но это можно сделать с помощью фоновых потоков для длительных действий, большинство из которых не будет проблемой. Мой первоначальный вопрос был, может быть, уже есть какая-то конкретная нить в области приложения, которая работает в Примере B, или на самом деле пример A - путь?

Фото Eclipse RAP: как управлять знаниями и доступом к базе данных

Вывод (пока)

В основном вариант А) - это путь. Для доступа к базе данных потребуется пул соединений, а для общей информации - вдумчивая синхронизация ключевых объектов. Главное внимание должно быть уделено проектированию базы данных и синхронизации объектов, чтобы гарантировать, что два клиента не могут записывать несовместимые данные одновременно (например, записывать противоречивые записи, которые делают результат зависимым от порядка записи).

1 ответ

Решение

Прежде всего, способ, которым вы создаете MyServer в первом фрагменте не является потокобезопасным. Вы можете создать более одного экземпляра MyServer,

Вам нужно синхронизировать создание MyServerвот так например:

synchronized( MyServer.class ) {
  MyServer myServer = (MyServer) appContext.getAttribute("myServer");
  if (myServer == null){
    myServer = new MyServer();
    appContext.setAttribute("myServer", myServer);
  }
}

Смотрите также этот пост Как реализовать поточную безопасную ленивую инициализацию? для других возможных решений.

Кроме того, ваш код звонит doSomething() в клиентском потоке (то есть в потоке пользовательского интерфейса), который заставит каждого клиента ждать обработки ожидающих запросов других клиентов. Пользовательский интерфейс клиента перестает отвечать на запросы.

Чтобы решить эту проблему, ваш код должен позвонить doSomething() (или любая другая длительная операция в этом отношении) из фонового потока (см. также Потоки в RAP)

Когда фоновый поток завершился, вы должны использовать Server Push для обновления пользовательского интерфейса.

Другие вопросы по тегам