Каков наилучший способ передачи информации между потоками?
Я хочу слушать сервер, пока моя программа делает другие вещи, когда сообщение получено с сервера, я хочу его интерпретировать.
Я знаю про потоки, но не совсем уверен, как это работает. Если у меня есть поток, слушающий сервер, как я могу передать эти данные в основной поток для интерпретации? Каков наилучший способ для основного потока отправлять данные на сервер? Что такое синхронизированный модификатор?
Ответы
Ответ 1
Если у меня есть поток, слушающий сервер, как я могу передать эти данные в основной поток для интерпретации? Каков наилучший способ для основного потока отправлять данные на сервер?
Я использовал бы BlockingQueue
. Вы определяете один BlockingQueue
, например LinkedBlockingQueue
. Затем ваш класс слушателя вызывает queue.take()
, который будет ждать, пока ваш сервер вызовет queue.put()
. Он оставляет всю синхронизацию, ждет, уведомляет и т.д. Для класса Java вместо вашего собственного кода.
Что такое синхронизированный модификатор?
Я бы немного почитал, чтобы больше узнать об этом. Это не та вещь, на которую можно ответить в коротком ИСО-ответе. Java concurrency учебник - это хорошее место для начала.
Ответ 2
Пройдите некоторые учебные пособия для понимания тем Java.
http://www.journaldev.com/1079/java-thread-tutorial
Ваша проблема, похоже, похожа на модель производителя-потребителя, вы можете использовать BlockingQueue для достижения этой задачи легко.
Java Blocking Queue
Ответ 3
Если вам нужна синхронная связь между основным потоком и потоком обработки, вы можете использовать SynchronousQueue.
Идея состоит в том, что основной поток передает данные в поток обработки, вызывая put()
, а поток обработки вызывает take()
. Обе операции блокировки.
Обратите внимание, что если вы хотите отправить результат, тогда ситуация может немного усложниться, поскольку основной поток должен знать, когда результат будет готов. A CountDownLatch - хороший примитив для этого. Вы можете сделать что-то вроде этого.
Сначала дайте определение структуры данных для передачи данных вокруг:
public class MethodCall {
public final String methodName;
public final Object[] args;
public final CountDownLatch resultReady;
public Object result;
public MethodCall(String methodName, Object[] args) {
this.methodName = methodName;
this.args = args;
this.resultReady = new CountDownLatch(1);
}
public void setResult(Object result) {
this.result = result;
resultReady.countDown();
}
public Object getResult() throws InterruptedException {
resultReady.await();
return result;
}
}
Определите очередь для передачи данных вокруг, видимых обоими потоками:
public SynchronousQueue<MethodCall> methodCalls = new SynchronousQueue<MethodCall>();
Чтобы сделать вызов из основного потока в поток обработки и дождаться результата:
MethodCall call = new MethodCall(methodName, args);
methodCalls.put(call);
Object result = call.getResult();
В потоке обработки, например, в методе run()
, вы можете:
for (;;) {
MethodCall call = methodCalls.take();
Object res = processStuff(call.methodName, call.args);
call.setResult(res);
}
Где processStuff
реализует вашу логику. Конечно, вы также должны иметь дело с исключениями, иметь дело с случаями выхода, изменить MethodCall
на более конкретные вещи, чем methodName
и args
и Object
return и т.д.