Отправка объектов туда и обратно между потоками в java?

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


person Kevin Q    schedule 02.12.2011    source источник
comment
Совместно использовать ссылку на объект между потоками легко, но нужна ли вам также передача сигналов между потоками? Например. чтобы позволить одному указать другому, пожалуйста, обработайте этот объект, а затем хорошо, обработка завершена, пожалуйста, обработайте возвращаемое значение.   -  person maerics    schedule 02.12.2011


Ответы (6)


Если вы хотите выполнить фактическую передачу сообщений, взгляните на Очередь синхронизации. Каждый поток будет иметь ссылку на очередь и будет ждать, пока один поток не передаст ссылку через очередь.

Это было бы потокобезопасно и отвечало бы вашим требованиям.

Хотя, если вы просто хотите, чтобы потоки читали и записывали общую переменную, вы можете использовать предложение normalocity, хотя его потокобезопасность зависит от того, как вы к нему обращаетесь (через sychronized или volatile)

person John Vint    schedule 02.12.2011
comment
+1 - это отличное расширение моей ссылки на общие коллекции объектов, и оно определенно подойдет. - person jefflunt; 02.12.2011

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

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

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

Один из методов обработки объектов и создания объектов результатов состоит в том, чтобы иметь общий массив или LinkedList, который действует как очередь объектов, содержащих объекты, подлежащие обработке, и объекты, полученные в результате этой обработки. Трудно вдаваться в подробности без подробностей о том, что именно вы пытаетесь сделать, но наиболее общий доступ к объектам между потоками сводится либо к вызовам методов между потоками, либо к некоторой общей коллекции/очереди объектов.

person jefflunt    schedule 02.12.2011
comment
shared array вы, вероятно, знаете это, но поскольку это не так ясно из чтения, предупреждение для других: энергозависимые массивы не равны энергозависимым элементам массива, поэтому вам в основном нужен небезопасный код - лучше использовать структуры данных высокого уровня. - person Voo; 02.12.2011

Если вы абсолютно не уверены, что это всегда будет только один объект за раз, используйте какую-либо очередь.

Если вы уверены, что это всегда будет только один объект за раз, в любом случае используйте какую-либо очередь. :-)

person user949300    schedule 02.12.2011

  • Используйте параллельную очередь из пакета java.util.concurrent.*.

Зачем? Почти гарантированно обеспечивает лучшую общую производительность, чем любая вещь, свернутая вручную.

Рекомендация: используйте связанную очередь, и вы получите обратное давление бесплатно.

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

  • Используйте семантику будущего

Зачем? Фьючерсы предоставляют проверенные и стандартные средства получения асинхронного результата.

Рекомендация: создайте простой класс Request и предоставьте метод #getFutureResponse(). Реализация этого метода может использовать различные стратегии сигнализации, такие как блокировка, флаг (с использованием Atomic/CAS) и т. д.

примечание: использование семантики тайм-аута в будущем позволит вам связать поведение сервера с SLA вашего сервера, например. #getFutureResponse(sla_timeout_ms).

person alphazero    schedule 02.12.2011

Совет по книге, если вы хотите немного больше погрузиться в взаимодействие между потоками (или процессами, или системами): Шаблонно-ориентированная архитектура программного обеспечения, том 2: шаблоны для параллельных и сетевых объектов

person The Nail    schedule 02.12.2011

Просто используйте простую внедрение зависимостей.

MyFirstThread extends Thread{
 public void setData(Object o){...}
}
MySecondThread extends Thread{
   MyFirstThread callback;
   MySecondThread(MyFirstThread callback){this.callback=callback)
}
MyFirstThread t1 = new MyFirstThread();
MySecondThread t2 = new MySecondThread(t1);    
t1.start();
t2.start();

Теперь вы можете выполнить callback.setData(...) во втором потоке.

Я считаю, что это самый безопасный способ. Другие решения включают использование volatile или какого-либо общего объекта, что я считаю излишним.

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

person Amir Raminfar    schedule 02.12.2011
comment
Зачем называть переменную обратного вызова? Не будет ли otherThread или что-то в этом роде иметь больше смысла? (В конце концов, это не функция) - person ; 02.12.2011
comment
Да, это тоже хорошая идея. Я просто назвал его callback, потому что хотел показать, что это то, что вызывает thread1. Но на самом деле это простое решение, которое показывает, что если вы можете передавать потоки, то вы можете делать что угодно. Вы также можете «синхронизировать» установщик/геттер. - person Amir Raminfar; 02.12.2011