Статьи

OSGi: PostEvent против SendEvent в новой теме


Этот пост показывает разницу между
postEvent и
sendEvent в osgi throw в примере. Согласно документации, пост-инициализация асинхронной доставки события и отправка является синхронной.

Но в чем разница между postEvent и новым потоком {void run () {
sendevent }}? Этот пост обрисовывает эту разницу на нескольких примерах.

Вступление

Пример состоит из двух пакетов:

1- Первый — для отправки сообщения и отправки события каждые 10 секунд, в двух разных очередях.

2. Во-вторых, зарегистрируйте два EventHanlers для каждой очереди и напечатайте полученное сообщение через 30 секунд.

Пакет уведомлений

Пакет активатора отправляет и публикует события, используя два разных потока, используя ServiceTracker для службы EventAdmin:

@Override
public void start(BundleContext bundleContext) throws Exception {
eventAdminTracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
eventAdminTracker.open();
eventAdmin = (EventAdmin) eventAdminTracker.getService();
if (eventAdmin != null) {
new Thread() {

@Override
public void run() {
try {
postEvent();
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();


new Thread() {

@Override
public void run() {
try {
sendEvent();
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();

}

postEvent () и sendEvent () идентичны, за исключением того, что они используют две разные очереди. Первый использует postEvent, а второй — методы sendEvent в EventAdmin. Сообщения будут отправляться каждые 10 с, содержащие текущее время отправки.

Сообщение событие SendEvent
private static final String POST_EVENT_QUEUE = "JTUNSIE/post";
private void postEvent() throws InterruptedException {
Dictionary props = new Properties();
int i = 0;
while (true) {
Date d = new Date();
props.put("property", "" + i++ + " : " + d);
System.out.println("before post : " + d);
Event event = new Event(POST_EVENT_QUEUE, props);
eventAdmin.postEvent(event);
System.out.println("after post : " + d);
Thread.sleep(10 * 1000);
}
}
private static final String SEND_EVENT_QUEUE = "JTUNSIE/send";
private void sendEvent() throws InterruptedException {
Dictionary props = new Properties();
int i = 0;
while (true) {
Date d = new Date();
props.put("property", "" + i++ + " : " + d);
System.out.println("before send ; " + d);
Event event = new Event(SEND_EVENT_QUEUE, props);
eventAdmin.sendEvent(event);
System.out.println("after send : " + d);
Thread.sleep(10 * 1000);
}
}

Пакет обработчика

Отметив здесь особенное. Пакет обработчиков регистрирует два EventHandler, один для POST_EVENT_QUEUE, а другой для SEND_EVENT_QUEUE. Они ждут 30 секунд обработки сообщений, прежде чем напечатать это время.

public class PostEventHandler implements EventHandler{

@Override
public void handleEvent(Event event) {
String value = event.getProperty("property").toString();
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("---------------->Post value : " + value);

}

}

public class SendEventHandler implements EventHandler{

@Override
public void handleEvent(Event event) {
String value = event.getProperty("property").toString();
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("---------------->Send value : " + value);

}

}

public class Activator implements  BundleActivator {

private static final String POST_EVENT_QUEUE = "JTUNSIE/post";
private static final String SEND_EVENT_QUEUE = "JTUNSIE/send";



@Override
public void start(BundleContext context) throws Exception {
Dictionary dp = new Hashtable();
dp.put(EventConstants.EVENT_TOPIC, POST_EVENT_QUEUE);
Dictionary ds = new Hashtable();
ds.put(EventConstants.EVENT_TOPIC, SEND_EVENT_QUEUE);

context.registerService(EventHandler.class.getName(), new PostEventHandler(), dp);
context.registerService(EventHandler.class.getName(), new SendEventHandler(), ds);
}

@Override
public void stop(BundleContext context) throws Exception {
}
}

Результат

Это вывод консоли:

перед сообщением: сб 26 сентября 12:39:30 CEST 2009

перед отправкой; Сб 26 сентября 12:39:30 CEST 2009

после сообщения: сб 26 сентября 12:39:30 CEST 2009

osgi> до сообщения: суббота 26 12:39:40 CEST 2009

после сообщения: сб 26 сентября 12:39:40 CEST 2009

до публикации: суббота, 26 сентября 12:39:50 CEST 2009

после публикации: суббота, 26 сентября 12:39:50 CEST 2009

—————-> Стоимость сообщения: 0: суббота 26 сентября 12:39:30 CEST 2009

до поста: сб 26 сентября 12:40:00 CEST 2009

после поста: сб 26 сен 12:40:00 CEST 2009

————— -> Отправьте значение: 0: сб 26 сентября 12:39:30 CEST 2009

после отправки: сб 26 сентября 12:39:30 CEST 2009

до публикации: сб 26 сентября 12:40:10 CEST 2009

после сообщения: сб 26 сентября 12:40:10 CEST 2009

перед отправкой; Сб 26 сентября 12:40:10 CEST 2009

Мы отмечаем,
что метод send ожидает печати «после отправки», пока обработчик не обработает сообщение, что означает, что отправитель все еще ожидает получателя. Метод post является лучшим решением для доставки асинхронного события без ожидания обработчика с немедленным возвратом.

Разница между postEvent и sendEvent с помощью темы

Согласно
спецификации CNMP версии 4.2 параграф 113.7.2 на стр. 352:

Асинхронная доставка событий инициируется методом postEvent. Когда

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

обработчики заинтересованы в событии. Собирая этот список обработчиков во

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

, зарегистрированные на момент публикации события, получат
уведомление о событии
.

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

В приложениях Entreprise OSGi мы должны зарегистрировать больше EventHandlers (> 100000), перечислив одну очередь. Отправка события в эту очередь с помощью post займет некоторое время, ожидая сбора всех обработчиков. Такое поведение блокирует событие post, как если бы это был синхронный процесс доставки.

Давайте зарегистрируем 50000 EventHandlers для нашего POST_EVENT_QUEUE

 for (int i = 0; i < 50000; i++) {
context.registerService(EventHandler.class.getName(), new MultiPostEventHandler(), dp);
}

где MultiPostEventHandler ничего не делает (без задержки), иначе печатает сообщение.

public class MultiPostEventHandler implements EventHandler {


@Override
public void handleEvent(Event event) {
String value = event.getProperty("property").toString();
System.out.println("---------------->Post value : " + value);

}
}

Заметим, что вывод нашей консоли спит более 10 с перед обработкой.

Вывод

Если вы хотите быть асинхронным способом, вам нужно использовать метод send или post внутри потока, когда у вас большое количество EventHandlers.

Примечание: исходный код находится под svn на кенае:
http://kenai.com/projects/posteventvssendevent/sources