Несколько потоков Java обращаются к одной строке - PullRequest
0 голосов
/ 20 июля 2011

У меня есть одна строка, к которой будут обращаться четыре разных потока в непредсказуемом порядке.

String s = "When value is";

Теперь выше строка s будет обновляться четырьмя различными потоками через Java Swing EDT. У меня есть два JCombobox и два JTextField. Внутри обработчика событий этих компонентов мне придется обновить приведенную выше строку.

Например, при изменении фокуса текстового поля строка должна быть «Когда значение равно X» при изменении комбо строка должна иметь значение «Когда значение меньше X и Y»

Так, как и выше, четыре потока будут менять одну строку. Если я не контролирую их, вывод будет неожиданным. Каков наилучший способ решить это. Я могу использовать join () или использовать volatile, но это усложнит код.

Пожалуйста, поделитесь своими идеями. Заранее спасибо.

Ответы [ 3 ]

6 голосов
/ 20 июля 2011

Во-первых, String является неизменным, поэтому его нельзя обновить. Однако другой объект, такой как компонент Swing, может содержать ссылку на String, и эта ссылка может быть обновлена, чтобы указывать на другой String. Это то, что обычно происходит, когда текст обновляется в графическом интерфейсе.

Если у вас есть четыре разных потока, которым необходимо обновить компонент Swing, например, чтобы отобразить другой String, они должны сделать это, поставив задачу в очередь для запуска в одном потоке диспетчеризации событий, используя SwingUtilities методы invokeLater или invokeAndWait, например,

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    myComponent.setText("New string");
  }
};

Или в более сложном приложении вы можете обновить объект домена, который затем должен быть потокобезопасным, из каждого из этих четырех потоков, а затем отдельно обновить компонент Swing в EDT. На мой взгляд, создать потокобезопасный код нелегко. Я настоятельно рекомендую книгу Параллелизм Java на практике , но суть заключается в том, чтобы гарантировать, что только один поток за раз выполняет любую операцию, в которой рассматриваемый объект временно находится в несовместимом состоянии. Иногда это возможно при подходящем использовании существующих потоковобезопасных классов и атомарных операций, но может потребовать использования блокировки, обычно с помощью synchronized методов или блоков.

Конечно, ничего из этого не имеет значения, если, как теперь кажется, у вас вообще нет четырех потоков, а только четыре обработчика событий, вызываемых в EDT.

1 голос
/ 20 июля 2011

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

Предположим, на мгновение вам нужно несколько событий в одном поле, и порядок действительно важен.Тем не менее, вы не доверяете EDT уведомлять события в том порядке, в котором они вам нужны.Можете ли вы продемонстрировать пример, где порядок будет неправильным и как вы собираетесь его исправить?

1 голос
/ 20 июля 2011

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

Нет способа контролировать этот порядок, даже для одного компонента. Попытка использовать join или какой-либо другой механизм блокировки просто приведет к зависанию вашего приложения.

Решение состоит в том, чтобы создать объект, который является посредником между входными источниками. Исходя из вашего описания, это может быть простой Map<String,String>, где ключ - это источник события, а значение - это то, что вы в конечном итоге хотите отобразить.

Каждый слушатель действия добавляет значение к этой карте, и когда добавляется 4-е значение, вы решаете, какое значение должно быть записано в вывод.

Затем вы очищаете карту, ожидая следующего набора входных данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...