Многопоточность в сессионном компоненте без состояния? - PullRequest
8 голосов
/ 28 сентября 2010

Спецификация EJB 3.0 не позволяет бизнес-методу сессионного компонента без сохранения состояния создавать новые потоки. Это почему? Что плохого в создании дополнительных рабочих потоков, которые выполняют только необработанные вычисления и никогда не обращаются к серверу приложений?

Скажем, мой сессионный компонент реализует сервис, который позволяет пользователям загружать изображения, а бизнес-метод выполняет интенсивную обработку изображений на этих изображениях. Тогда он может использовать только одно ядро ​​процессора, чтобы сделать эту работу, даже если машина имеет 8 или более ядер? Если бы я использовал стороннюю библиотеку обработки изображений, которая внутренне создает рабочие потоки, я бы также нарушил спецификации EJB, даже если эта библиотека и эти потоки не имеют никакого отношения к контейнеру EJB вообще. Это не кажется правильным.

Что может произойти, если я игнорирую правила EJB и все еще создаю несколько рабочих потоков для интенсивной обработки ЦП? Конечно, эти потоки никогда не будут касаться каких-либо объектов сервера приложений, и поток бобов присоединится к ним перед возвратом. Может ли случиться что-то плохое?

Ответы [ 4 ]

18 голосов
/ 29 сентября 2010

Спецификация EJB 3.0 не позволяет бизнес-методу сессионного компонента без сохранения состояния создавать новые потоки. Почему это так?

Краткая версия: управление потоками из EJB запрещено, потому что это может нанести ущерб управлению ресурсами, управлению транзакциями, безопасности (технические причины), а также потому, что это то, что модель EJB не хочет продвигать (философская причина).

В спецификации EJB это выглядит так:

21.1.2 Ограничения программирования

...

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

Эти функции зарезервированы для контейнера EJB. Разрешение корпоративному бину управлять потоками уменьшит способность контейнера правильно управлять средой выполнения.

Смотри также

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

Что я могу сказать, не используйте EJB, если вам это не нравится.

Что может произойти, если я проигнорирую правила EJB и по-прежнему создаю несколько рабочих потоков для интенсивной обработки ЦП? Конечно, эти потоки никогда не будут касаться каких-либо объектов сервера приложений, и поток бобов присоединится к ним перед возвратом. Может ли что-то еще случиться?

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

Если вы хотите «порождать» потоки стандартным способом, используйте API WorkManager или JMS.

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

1 голос
/ 20 июня 2017

Один тип обходного пути:

import java.util.concurrent.Executor;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

@Stateless
public class TransactionalExecutor implements Executor {

    @Override @Asynchronous
    public void execute(Runnable command) {
        command.run();
    }
}

Теперь вы можете использовать TransactionalExecutor в качестве исполнителя:

@Stateless
public class SlowService {

    @Inject
    Executor command;

    public void invoke(){
        Runnable command = new Runnable() {
            @Override
            public void run() {
                // heavy task
            }
        };
        command.execute(command);
    }    
}
1 голос
/ 14 августа 2014

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

Но вы все равно можете легко выполнять многопоточность с помощью аннотации @Asynchronous (есть и другие способы).

@Stateless
public class Employee {
    @Asynchronous
    public Future<Void> work(Project projectThatTakeTooLong) {
        // work work work
        return new AsyncResult<Void>(null);
    }
}

@Stateless
public class Boss {

    @Inject
    private Employee randomStatelessEmployee;

    public void giveWork() {
        Future<Void> result1 = randomStatelessEmployee.work(new Project());
        Future<Void> result2 = randomStatelessEmployee.work(new Project());
        Future<Void> result3 = randomStatelessEmployee.work(new Project());
        result1.get();
        result2.get();
        result3.get();
    }
}

Здесь также есть лучший пример: Контейнер Jboss Java EE и служба ExecutorService

0 голосов
/ 29 сентября 2010

Это известное ограничение не использовать потоки в приложениях J2EE. Сервер приложений должен позаботиться о параллельном выполнении программы

Да, вы можете игнорировать правила EJB, но можете столкнуться с крайне непредсказуемым поведением .

...