Solution generate N * N Documents

0

I have a problem. My project in spring boot receives a JSON (mapped to pojo with JACKSON) of options and an XML that we will call XML ORIGINAL.

Each option comes with a series of tags that must be modified on the original XML.

Suppose a JSON with:

 Opcion 1 = N valores;
 Opcion 2 = M valores;
 Opcion 3 = K valores;
 .....
 Opcion X = R valores

Each option must generate X variations based on the values I have. Eg: For the ORIGINAL XML I must generate N variations for the Option 1, Option 2 must generate M variations of the documents resulting from Option 1, Option 3 must generate K variations of the resulting documents of Option 2, Option X must generate R variations of documents resulting from Option 3.

In synthesis, you should give me variations of NxMxKxR XML ORIGINALS.

Following my algorithm, I get the following error:

  

2018-12-04 11: 37: 55.125 WARN 7296 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool: HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta = 49s823ms348μs491ns)

My variation is generated in the following way:

    package com.example.restproyect.states;

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Hashtable;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;

    import javax.persistence.Transient;

    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;

    import com.example.restproyect.Documento;
    import com.example.restproyect.filtros.FiltroAbs;
    import com.example.restproyect.filtros.FiltroNombre;
    import com.example.restproyect.hilos.Tarea;
    import com.example.restproyect.hilos.TareaRastrojo;
    import com.example.restproyect.states.objetosinternos.Pastura;
    import com.fasterxml.jackson.annotation.JsonAnyGetter;
    import com.fasterxml.jackson.annotation.JsonAnySetter;
    import com.fasterxml.jackson.annotation.JsonIgnore;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.annotation.JsonPropertyOrder;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonPropertyOrder({ "digestibilidadVariaciones", "rindeVariaciones" })
    public class Rastrojo implements Serializable{

        @JsonProperty("digestibilidadVariaciones")
        private List<Pastura> digestibilidadVariaciones = null;

        @JsonProperty("rindeVariaciones")
        private List<Pastura> rindeVariaciones = null;

        @Transient
        private FiltroAbs filtro = new FiltroNombre("crop_stubbles");

        @JsonIgnore
        private Map<String, Object> additionalProperties = new HashMap<String, Object>();

        @JsonAnyGetter
        public Map<String, Object> getAdditionalProperties() {
            return this.additionalProperties;
        }

        @JsonAnySetter
        public void setAdditionalProperty(String name, Object value) {
            this.additionalProperties.put(name, value);
        }



        public List<Pastura> getDigestibilidadVariaciones() {
            return digestibilidadVariaciones;
        }

        public void setDigestibilidadVariaciones(List<Pastura> digestibilidadVariaciones) {
            this.digestibilidadVariaciones = digestibilidadVariaciones;
        }

        public List<Pastura> getRindeVariaciones() {
            return rindeVariaciones;
        }

        public void setRindeVariaciones(List<Pastura> rindeVariaciones) {
            this.rindeVariaciones = rindeVariaciones;
        }

        public void setAdditionalProperties(Map<String, Object> additionalProperties) {
            this.additionalProperties = additionalProperties;
        }

        @Override
        public String toString() {
            return "Rastrojo [digestibilidadVariaciones=" + digestibilidadVariaciones + ", rindeVariaciones="
                    + rindeVariaciones + ", additionalProperties=" + additionalProperties + "]"+"\n";
        }

        public static ArrayList<Pastura> cloneList( List<Pastura> list) {
             ArrayList<Pastura> clone = new ArrayList<Pastura>(list.size());
            for (Pastura item : list) 
                clone.add(item.clone());
            return clone;
        }

        public Hashtable<Integer, Documento> generarEscenarios(Hashtable<Integer, Documento> escenarios) {
            Hashtable<Integer, Documento> newEscenarios = new Hashtable<Integer, Documento>();
            //Numero de threads
            ExecutorService executor = Executors.newFixedThreadPool(100);
            ArrayList<Future<ArrayList<Documento>>> listFuture = new ArrayList<>();
            //Por cada escenario que entre. Los escenarios arrancan en 1
            for(int indexEscenarios = 0; indexEscenarios < escenarios.size(); indexEscenarios++) {
                //Generar para ese escenario, la variacion correspondiente
                listFuture.add(executor.submit(new TareaRastrojo(
                                                cloneList(digestibilidadVariaciones), 
                                                cloneList(rindeVariaciones), filtro,escenarios.get(indexEscenarios), indexEscenarios)));

            }       
            while(!executor.isTerminated()) {

            }       
            int count = 1;
            for(Future<ArrayList<Documento>> resultado:listFuture){
                if(resultado.isDone()){
                    try {
                        for(Documento doc:resultado.get()) {
                            System.out.println("---------------------------AGREGANDO ESCENARIO["+count+"]---------------------------------------");
                            count++;
                            //newEscenarios.put(newEscenarios.size(), doc);
                        }
                        //System.out.println("-------CANTIDAD DE ESCENARIOS------["+newEscenarios.size()+"]");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }             
            }                       

            System.out.println("-------CANTIDAD DE ESCENARIOS------");
            System.out.println("-------CANTIDAD DE ESCENARIOS------["+newEscenarios.size()+"]");
            return newEscenarios;
        }





    }

Cada TareaRastrojo es un Objeto que se comporta asi:

package com.example.restproyect.hilos;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.Callable;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.example.restproyect.Documento;
import com.example.restproyect.filtros.FiltroAbs;
import com.example.restproyect.states.objetosinternos.Pastura;

    public class TareaRastrojo implements Callable<ArrayList<Documento>>{

        private ArrayList<Pastura> digestibilidadVariaciones;
        private ArrayList<Pastura> rindeVariaciones;
        private FiltroAbs filtro;
        private Documento doc;
        private int numero;



        public TareaRastrojo(ArrayList<Pastura> digestibilidadVariaciones, ArrayList<Pastura> rindeVariaciones, FiltroAbs filtro,
                Documento doc, int numero) {
            super();
            this.digestibilidadVariaciones = digestibilidadVariaciones;
            this.rindeVariaciones = rindeVariaciones;
            this.filtro = filtro;
            this.doc = doc;
            this.numero = numero;
        }



        public ArrayList<Documento> call() {    
            ArrayList<Documento> documentosGenerados = new ArrayList<>();
            System.out.println("***************************************************************************************");
            System.out.println("Documento numero ="+this.numero);
            for(int indexVariaciones = 0; indexVariaciones < digestibilidadVariaciones.get(0).getPasturas().size(); indexVariaciones++) {
                Document newDocument = this.doc.getDocumento();         
                System.out.println("Variacion numero["+indexVariaciones+"] de la tarea numero ["+this.numero+"]");
                Documento doc = new Documento(newDocument);         
                Document insertDoc = doc.clonarDocumento();
                newDocument = null;

                doc.setDocumento(insertDoc);

                //Para cada tag dentro del tag <escenario> Busco los tags que tienen las variaciones
                NodeList node = doc.getDocumento().getChildNodes().item(0).getChildNodes();     
                for(int j=0; j < node.getLength(); j++) {
                    /*
                     * indice par es un text dentro de los tags, solo 
                     * se trabaja con los elementos impares
                     * que son los TAGS
                     */
                    if(j%2 != 0) {

                            Node nodo =  node.item(j);
                            if(filtro.cumple(nodo)) {
                                //Obtengo la pastura a variar                               
                                NodeList nodePastura = node.item(j).getChildNodes();                        

                                for(int indexPastura = 0; indexPastura < digestibilidadVariaciones.size(); indexPastura++) {                
                                    //Formula para obtener la pastura que va a variar
                                    System.out.println("Variacion numero["+indexVariaciones+"] de la tarea numero ["+this.numero+"] de la PASTURA ["+indexPastura+"]");
                                    Node nodoPastura = nodePastura.item(indexPastura*2+1);  
                                    nodoPastura.getAttributes().getNamedItem("crop_stubbleDigest").setNodeValue(String.valueOf(digestibilidadVariaciones.get(indexPastura).next()));
                                    nodoPastura.getAttributes().getNamedItem("yield").setNodeValue(String.valueOf(rindeVariaciones.get(indexPastura).next()));
                                    System.out.println("FIN DE LA Variacion numero["+indexVariaciones+"] de la tarea numero ["+this.numero+"] de la PASTURA ["+indexPastura+"]");
                                }   
                                System.err.print("FIN DE LA Variacion numero["+indexVariaciones+"] de la tarea numero ["+this.numero+"]");
                                documentosGenerados.add(doc);

                            }       
                    }                   

                }
            }
            for(int indexPastura = 0; indexPastura < digestibilidadVariaciones.size(); indexPastura++) {                                
                digestibilidadVariaciones.get(indexPastura).resetUltimaSeleccion();
                rindeVariaciones.get(indexPastura).resetUltimaSeleccion();
            }
            System.err.println("Finalizando Documento numero ="+this.numero);
            System.out.println("***************************************************************************************");
            return documentosGenerados;         

        }




    }


    package com.example.restproyect.states.objetosinternos;

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import com.fasterxml.jackson.annotation.JsonAnyGetter;
    import com.fasterxml.jackson.annotation.JsonAnySetter;
    import com.fasterxml.jackson.annotation.JsonIgnore;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.annotation.JsonPropertyOrder;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonPropertyOrder({ "pasturas" })
    public class Pastura implements Serializable,Cloneable{

        @JsonProperty("pastura")
        private List<Integer> pasturas = null;

        private int ultimaSeleccion = 0; 

        @JsonIgnore
        private Map<String, Object> additionalProperties = new HashMap<String, Object>();


        public Pastura(ArrayList<Integer> pasturas) {
            super();
            this.pasturas = pasturas;
        }

        public Pastura(List<Integer> pasturas, Map<String, Object> additionalProperties) {
            super();
            this.pasturas = pasturas;
            this.additionalProperties = additionalProperties;
        }

        @JsonAnyGetter
        public Map<String, Object> getAdditionalProperties() {
            return this.additionalProperties;
        }

        @JsonAnySetter
        public void setAdditionalProperty(String name, Object value) {
            this.additionalProperties.put(name, value);
        }

        public List<Integer> getPasturas() {
            return pasturas;
        }

        public void setPasturas(List<Integer> pasturas) {
            this.pasturas = pasturas;
        }

        public void setAdditionalProperties(Map<String, Object> additionalProperties) {
            this.additionalProperties = additionalProperties;
        }


        public float next() {
            float valor = this.pasturas.get(this.ultimaSeleccion);
            this.ultimaSeleccion = this.ultimaSeleccion + 1;
            return valor;
        }



        public void resetUltimaSeleccion() {
            this.ultimaSeleccion = 0;
        }

        @Override
        public String toString() {
            return "Pastura [pasturas=" + pasturas + ", additionalProperties=" + additionalProperties + "]";
        }

        public Pastura clone(){
            return new Pastura(new ArrayList<Integer>(this.pasturas)); //new ArrayList<Integer>(this.pasturas);
        }
    }

The context switching of the threads work well, where I can see how the messages appear in disorder

The problem is that the CPU goes to 100% and does not finish its execution, missing 500 scenarios to be generated.

It should be noted that I am trying to generate 5 ^ 5 documents = 3125 and generate them well, but by generating the next level that would give 5 ^ 6 = 15625 in the generation of scenario 11000 to 12000, the CPU is stuck. It does not end in the same scenario but it varies. Any idea why it may be hanging?

100% CPU

    
asked by Maxi Roselli 05.12.2018 в 20:27
source

1 answer

0

This loop should be firing the cpu:

    while(!executor.isTerminated()) {

    }    

Be sure to use taskExecutor.awaitTermination(..) or at least put a Thread.sleep(2000) to free the cpu.

On the other hand you can also explore the option to put a cap on concurrent threads to the executor.

    
answered by 06.12.2018 в 16:13