2016-05-13 4 views
0

Я работаю в LR 6.2 CE GA4 Clustered environment. 2 узла используют один и тот же БД с общим кэшем через конфигурацию кластера портала-ext.Обработка параллелизма в кластере Liferay

У меня есть планировщик, вызывающий метод processMe() каждые 15 минут, который также может быть вызван пользователем при нажатии на страницу.

Моим требованием является ограничение одновременного вызова этого метода. Я понимаю, что синхронизированные блоки не работают из-за разных JVM.

Есть ли что-нибудь, что я могу повторно использовать OOTB изнутри Liferay? Могу ли я повторно использовать что-то из одноадресной/многоадресной связи JGroups?

Любые другие предложения?

Опубликовано в Liferay форуме:https://web.liferay.com/community/forums/-/message_boards/message/74168121

Спасибо,

Сиби Матфей

+0

Где бы вы хотели бы получить ответ? Вот? Или на форуме Лиферэй? В другом месте? Пожалуйста, прочитайте http://meta.stackexchange.com/questions/141823/why-is-cross-posting-wrong-on-an-external-site и обновите/link/delete соответственно –

+0

Я добавил ссылку на свой пост в liferay Форум – simplysiby

ответ

0

Я нашел решение после того, как со ссылкой на метод: com.liferay.portal.kernel.backgroundtask.SerialBackgroundTaskExecutor .acquireLock()

Вот код:

@Override 
    public BackgroundTaskResult execute(BackgroundTask backgroundTask) 
     throws Exception { 

    Lock lock = null; 

    String owner = 
     backgroundTask.getName() + StringPool.POUND + 
      backgroundTask.getBackgroundTaskId(); 

    try { 
     if (isSerial()) { 
      lock = acquireLock(backgroundTask, owner); 
     } 

     BackgroundTaskExecutor backgroundTaskExecutor = 
      getBackgroundTaskExecutor(); 

     return backgroundTaskExecutor.execute(backgroundTask); 
    } 
    finally { 
     if (lock != null) { 
      LockLocalServiceUtil.unlock(
       BackgroundTaskExecutor.class.getName(), 
       backgroundTask.getTaskExecutorClassName(), owner); 
     } 
    } 
} 

protected Lock acquireLock(BackgroundTask backgroundTask, String owner) 
     throws DuplicateLockException { 

    Lock lock = null; 

    while (true) { 
     try { 
      lock = LockLocalServiceUtil.lock(
       BackgroundTaskExecutor.class.getName(), 
       backgroundTask.getTaskExecutorClassName(), owner); 

      break; 
     } 
     catch (SystemException se) { 
      if (_log.isDebugEnabled()) { 
       _log.debug("Unable to acquire acquiring lock", se); 
      } 

      try { 
       Thread.sleep(50); 
      } 
      catch (InterruptedException ie) { 
      } 
     } 
    } 

    if (!lock.isNew()) { 
     throw new DuplicateLockException(lock); 
    } 

    return lock; 
} 

Основное изменение в моем коде было проверить

if (!lock.isNew()) { 
throw new DuplicateLockException(lock); 
} 

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

Следовательно lock.isNew() должен найти нить, которая удерживает реальный замок.

Спасибо,

Сиби Мэтью

Смежные вопросы