Pregunta

Estoy escribiendo una aplicación Java EE usando puntales y primavera.En una de las operaciones hay un procesamiento de bases de datos pesadas y, por lo tanto, problemas de rendimiento.Lo que quiero saber es ¿puedo usar MultiPhreading aquí?Creo que la especificación Java EE no permite que se cree hilos personalizados aparte de los creados por el servidor (utilizo WEBLOGIC).Por favor, guíame a través de esto.

¿Fue útil?

Solución

Esta pregunta aparece de vez en cuando.

Según la especificación no está autorizada. La mejor página para ver es esta: Q / A: Restricciones J2EE

Dicho esto, hay maneras de generar hilos, especialmente en Weblogic con el WorkManager.

VER ESTAS PREGUNTAS:

El hecho de que el primero objetivo EJB no debería importarlo, y el último sobre el acceso al sistema de archivos se trata de restricciones generales.

espero que ayude.

Otros consejos

La forma recomendada de crear hilos en un entorno Java EE, es con la API de Concurrency Utils, que forma parte de la especificación EE7.

Al utilizar esta API, se creará su nuevo hilo, y administrará el contenedor, garantizando que todos los servicios EE estén disponibles para su hilo (por ejemplo, seguridad, transacciones).

Los siguientes ejemplos se toman de mi propio sitio aquí y aquí

usando un administradorExecutorService

Para crear un nuevo hilo usando un Ejemplo de Ejército, primero cree un objeto de tarea que implemente que se pueda llamar. Dentro del método Call () definiremos el trabajo que queremos llevado a cabo en un hilo separado.

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();
    }
}

Entonces debemos invocar la tarea al pasarlo a través del método de envío () del administrador de Ejército.

@Stateless
public class ReportBean {

    @Resource
    private ManagedExecutorService executorService;

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

usando una factura administrada

Primero cree una tarea corrupable que definirá qué trabajo se debe hacer en el fondo.

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);
        }
    }
}

Para obtener un hilo administrado de contenedores, simplemente le preguntamos a la facturación administrada para un hilo nuevo y pasemos nuestra instancia de ejecución. Para iniciar el hilo llamamos inicio ().

@Stateless
public class ReportBean {

    @Resource
    private ManagedThreadFactory threadFactory;

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

Estas restricciones están en su lugar principalmente porque Java EE y EJB quieren apoyar la agrupación transparente.Por ejemplo, un servidor de un clúster no debe modificar los archivos porque estos cambios no se pueden reflejar fácilmente a otros servidores.Para los hilos existe la pregunta si debe haber un hilo por clúster o por servidor.Estos hilos también no pueden ser monitoreados fácilmente por el servidor de aplicaciones.

Dicho esto, debe ser posible crear hilos, conexiones de socket o acceder al sistema de archivos en un servidor Java EE al igual que en una aplicación normal.

Si necesita ejecutar varios hilos aquí es una sugerencia (o forma alternativa) con el grupo de control simple:

1 - Pase su contexto (EJB) como parámetro a su método (Punto final, programador, métodos de predeterminado)

2 - Controle el estado con programador complementario o banderas de entidad 3 - Tenga cuidado con el volumen de datos / procesamiento

4 - Recomendaciones: métricas, registros y pruebas, pruebas, pruebas se recomiendan fuertemente

5: este código está en Springboot, pero se probó en JBoss (con modificaciones) en el contexto de EJB: prueba cuidadosamente

6 - Use / modifique como desee: (Enviar sugerencias / comentarios)

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";
    }
}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top