Вопрос

Я пишу приложение Java EE, используя стойки и весну.В одной из операций существует тяжелая обработка базы данных и, следовательно, проблемы с производительностью.Что я хочу знать, это я могу использовать здесь многопоточье?Я думаю, что спецификация Java EE не позволяет создавать пользовательские потоки отдельно от созданных сервером (я использую Weblogic).Пожалуйста, проведите меня через это.

Это было полезно?

Решение

Этот вопрос всплывает время от времени.

согласно спецификации, это не авторизовано. Лучшая страница, на которую можно посмотреть, это одна: q / a: j2ee Ограничения

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

См. Эти вопросы:

Тот факт, что первые цели EJB должны не иметь значения, и последний о доступе к файловой системе - это общие ограничения.

Надеюсь, это поможет.

Другие советы

Рекомендуемый способ создания потоков в среде Java EE, с помощью API Consullency Utils, которая является частью спецификации EE7.

Используя эту API, будет создан ваша новая тема и управляется контейнером, гарантируя, что все услуги EE доступны в вашу нить (например, безопасность, транзакции).

Приведенные ниже примеры взяты с моего собственного сайта здесь и Здесь

<Сильные> Использование управляемогоExecutorservice

Чтобы создать новую тему с использованием управляемогоExecutorservice, сначала создайте объект задач, который реализует Callable. В рамках метода CALL () мы определим работу, которую мы хотим выполнить в отдельном потоке.

public class ReportTask implements Callable<Report> {

    Logger logger = Logger.getLogger(getClass().getSimpleName());

    public Report call() {
        try {
            Thread.sleep(3000);
        catch (InterruptedException e) {
            logger.log(Level.SEVERE, "Thread interrupted", e);
        }
        return new Report();
    }
}
.

Тогда нам нужно вызывать задачу, прошедшая ее, хотя на передачу () метода управляющегоExecutorservice.

@Stateless
public class ReportBean {

    @Resource
    private ManagedExecutorService executorService;

    public void runReports() {
        ReportTask reportTask = new ReportTask();
        Future<Report> future = executorService.submit(reportTask);
    }
}
.

Использование управляющей сети

Сначала создайте задачу Runnable, которая будет определять, какая работа должна быть сделана на заднем плане.

public class ReportTask implements Runnable {

    Logger logger = Logger.getLogger(getClass().getSimpleName());

    public void run() {
        try {
            //do your background task
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            logger.log(Level.SEVERE, "Thread interrupted", e);
        }
    }
}
.

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

@Stateless
public class ReportBean {

    @Resource
    private ManagedThreadFactory threadFactory;

    public void runReports() {
        ReportTask reportTask = new ReportTask();
        Thread thread = threadFactory.newThread(reportTask);
        thread.start();
    }
}
.

Эти ограничения находятся в основном, потому что Java EE и EJB хотят поддерживать прозрачную кластеризацию.Например, один сервер кластера не должен изменять файлы, поскольку эти изменения не могут быть легко отражены на других серверах.Для потоков есть вопрос, если должен быть один нить на кластер или на сервер.Эти потоки также не могут быть легко контролироваться сервером приложений.

, которое сказано, что должно быть возможно создать потоки, соединения сокетов или доступ к файловой системе в сервере Java EE, как в обычном приложении.

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

1 - пропустите свой контекст (EJB) в качестве параметра к вашему методу (end конечная точка, планировщик, методы по умолчанию)

2 - Управление состоянием с дополнительными флагами планировщика или объекта 3 - Будьте осторожны с объемом данных / обработки

4 - Рекомендации: Метрики, журналы и тесты, тесты, тесты настоятельно рекомендуются

5 - этот код на Springboot, но был протестирован в JBOSS (с модификациями) в контексте EJB - проверьте тщательно

6 - Используйте / изменить, как вы хотите: (отправлять предложения / комментарии)

basecontrolexecutor.java

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;


public class BaseControlExecutor {

    private final ScheduledThreadPoolExecutor poolExec = new ScheduledThreadPoolExecutor(2);

    public void execWithTimeout(final Runnable runnable, long timeout,
            TimeUnit timeUnit) throws Exception {
        execWithTimeout(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                runnable.run();
                return null;
            }
        }, timeout, timeUnit);
    }

    public <T> T execWithTimeout(Callable<T> callable, long timeout,    TimeUnit timeUnit) throws Exception {

        final Future<T> future = poolExec.submit(callable);

        try {
            return future.get(timeout, timeUnit);
        } catch (TimeoutException e) {
            future.cancel(true);
            throw e;
        } catch (ExecutionException e) {
            Throwable t = e.getCause();
            if (t instanceof Error) {
                throw (Error) t;
            } else if (t instanceof Exception) {
                throw (Exception) t;
            } else {
                throw new IllegalStateException(t);
            }
        }
    }
}
.

EndPointControlRest.java

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping(value = "/report")
@Api(tags = "Endpoint of Future")
public class EndpointControlRest extends BaseControlExecutor {

    Logger logger = LoggerFactory.getLogger(EndpointControlRest.class);

    //single metric of execution
    protected final AtomicLong counter = new AtomicLong();

    @GetMapping(path = "/withThread", produces = { "application/json" })
    @ApiOperation(value = "Return Hello count.")
    public String greeting() {

        Long countRunner = counter.incrementAndGet();
        String json = ""; //or EJB context to use in Thread - becareful

        new Thread(() -> {

            try {
                execWithTimeout(new Runnable() {
                    @Override
                    public void run() {

                        Instant start = Instant.now();
                        logger.info("Report init - " + countRunner);

                        //generating reports
                        generateBackgroundReport(json);

                        logger.info("Report End - " + countRunner);

                        Instant finish = Instant.now();
                        long timeElapsed = Duration.between(start, finish).toMillis();

                        logger.info("###DEBUG - " + countRunner + " - OK |Time exe: " + timeElapsed);

                    }
                }, 120, TimeUnit.SECONDS);
            } catch (TimeoutException e) {
                logger.info("###DEBUG - " + countRunner + " - Timeout - " + e.getMessage());
            } catch (Exception e) {
                logger.info("###DEBUG - " + countRunner + " - Exception - " + e.getMessage());
            }
        }).start();

        logger.info("####DEBUG - Rest call released");
        return "Hello " + countRunner;
    }

    public String generateBackgroundReport(String json){

        //simulating work
        Long x = 0L;
        for(Long i = 0L; i < 1000000000L; i ++){
            x = i + 1;
        }
        logger.info("####DEBUG -report: " + x);
        return "OK";
    }
}
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top