Domanda

Sto scrivendo un'applicazione Java EE usando montanti e primavera.In una delle operazioni c'è un pesante elaborazione del database e quindi questioni prestazionali.Quello che voglio sapere è posso usare il multithreading qui?Penso che la specifica Java EE non consenta di creare i thread personalizzati da quelli creati dal server (Io uso weblogic).Per favore guidami attraverso questo.

È stato utile?

Soluzione

Questa domanda si apre una volta ogni tanto.

Secondo le specifiche non è autorizzato. La pagina migliore da guardare è questa: Q / A: restrizioni J2ee

Detto questo, ci sono modi per generare fili, especial in weblogic con il WorkManager.

Vedi queste domande:

Il fatto che il primo bersaglia l'EJB non dovrebbe importare così tanto, e l'ultimo sull'accesso al file system riguarda le restrizioni generali.

Spero che aiuti.

Altri suggerimenti

Il modo consigliato per creare discussioni in un ambiente Java EE, è con l'API di Concurrency Utils, che fa parte della specifica EE7.

Utilizzando questa API il nuovo thread verrà creato e gestito dal contenitore, garantendo che tutti i servizi EE sono disponibili per il thread (ad es. Security, transazioni).

Gli esempi di seguito sono tratti dal mio sito qui e qui

Utilizzo di un manageDexecutorservice

Per creare un nuovo thread utilizzando un manageDexecutorservice, creare innanzitutto un oggetto attività che implementa il Chiackable. All'interno del metodo di chiamata () definiremo il lavoro che vogliamo eseguire in un filo separato.

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

Quindi dobbiamo richiamare il compito passandolo però al metodo di invio () del ManageDexecuutorservice.

@Stateless
public class ReportBean {

    @Resource
    private ManagedExecutorService executorService;

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

Utilizzo di un managedthreadFactory

Prima crea un'attività runnicabile che definisce quale lavoro deve essere fatto sullo sfondo.

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

Per ottenere un thread gestito da un contenitore, chiediamo semplicemente il managedthreadFactory per un nuovo thread, e passiamo la nostra istanza runnica. Per avviare il filo che chiamiamo Avvio ().

@Stateless
public class ReportBean {

    @Resource
    private ManagedThreadFactory threadFactory;

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

Queste restrizioni sono in atto per lo più perché Java EE ed EJB vogliono supportare il clustering trasparente.Ad esempio, un server di un cluster non deve modificare i file perché queste modifiche non possono essere facilmente rispecchiate ad altri server.Per i thread c'è la domanda se dovrebbe esserci un thread per cluster o per server.Questi thread non possono anche essere facilmente monitorati dal server delle applicazioni.

Detto questo, dovrebbe essere possibile creare thread, collegamenti socket o accedere al filesystem in un server Java EE come in una normale applicazione.

Se è necessario eseguire diversi thread qui è un suggerimento (o un modo alternativo) con semplice controllo del controllo:

1 - Passa il contesto (EJB) come parametro sul tuo metodo (REST Endpoint, Scheduler, Metodi di default)

2 - Controlla lo stato con scheduler complementari o flag di entità 3 - Fai attenzione al volume di dati / elaborazione

4 - Raccomandazioni: metriche, registri e test, test, test sono fortemente consigliati

5 - Questo codice è su SpringBoot ma è stato testato in JBoss (con modifiche) nell'ambito del contesto EJB - Test attentamente

6 - Usa / modifica come desideri: (Invia suggerimenti / commenti)

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top