Descomposición factorial con hilos II

Descomposición factorial con hilos II
Y ahora vamos a emular un lugar donde se descomponen los números y cada vez que se encuentra uno, se obtiene y se muestra su descomposición.

Para realizar esto, usaremos los monitores de Java, los métodos wait() y notify(). Estos métodos tienen que ir siempre incluidos sobre métodos marcados como syncronized o usar el método syncronized(metodo sincronizado). wait() y notify() (hay alguno más) heredan del Object, por lo que todos los objetos que hereden de esta clase, lo tienen disponible.

¿Que hace wait()? suspende indefinidamente el hilo hasta que se reanude con notify().

Así que crearé una clase que solicitará la descomposición del número, el cual es enviado al supuesto servidor compartido de descomposiciones factoriales, este se encarga de descomponerlo (tarea dura) y una vez que termine, habrá un receptor de datos esperando a su finalización para mostrar su descomposición.

DESC

La clase SolicitudDescomposicionVisualizadorDescomposicion heredan de Thread, los iniciamos desde la clase principal y a trabajar por parte del servidor. He aquí el código:

public static void main(String[] args) {
        // TODO code application logic here
        
        ServidorDescomposicion r=new ServidorDescomposicion();
        for (int i = 0; i < 10; i++) {
            SolicitudDescomposicion productor=new SolicitudDescomposicion(i, r);
            VisualizadorDescomposicion consumidor=new VisualizadorDescomposicion(i, r);
            
            productor.start();
            consumidor.start();
        }
        
    }
public class SolicitudDescomposicion extends Thread {
    
    ServidorDescomposicion r;
    
    public SolicitudDescomposicion(int n, ServidorDescomposicion _r){
        this.setName("Productor " + n);
        r=_r;
    }
    
    @Override
    public void run(){
        int n=Math.abs(new Random().nextInt());
        System.out.println("Enviando número descomposición desde el productor:\t" + n);
        r.descomponerNumero(n);
    }
}

public class VisualizadorDescomposicion extends Thread{
    
    ServidorDescomposicion r;
    
    public VisualizadorDescomposicion(int n, ServidorDescomposicion _r){
        this.setName("Consumidor " + n);
        r=_r;
    }
    
    @Override
    public void run(){        
        String desc="";
        try {
            desc = r.getDescomposicion();
        } catch (InterruptedException ex) {
            Logger.getLogger(VisualizadorDescomposicion.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Datos obtenidos desde el consumidor.Resultado:\t\t" + desc);        
    }
}
public class ServidorDescomposicion {

    ArrayList buffer;
    boolean existData;


    //&& estado.equals(estadoEnum.DESCOMPONIENDO
    //&& estado.equals(estadoEnum.LIBRE)
    public ServidorDescomposicion() {
        buffer = new ArrayList();
    }

    public synchronized void descomponerNumero(int numero) {
        descomponer(numero);
    }

    void retardo(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException ex) {
            Logger.getLogger(ServidorDescomposicion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public synchronized String getDescomposicion() throws InterruptedException {
        
        while(!existData){
            try {
                wait();
            } catch (InterruptedException ex) {
                Logger.getLogger(ServidorDescomposicion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        String descomposicion = "";
        descomposicion = buffer.remove(0);
        if (buffer.size()==0) {
            existData=false;
        }
        notify();
        
        return descomposicion;
    }

    void descomponer(int numero) {
        // Cálculos y resultados
        int iniNum = numero;
        int numeroAux = numero;
        int n = 0;
        int nn = 0;

        String text = "";
        String puntos = ".";

        for (long i = 2; i < numero; i++) { 
            while (numeroAux % i == 0) {
                numeroAux /= i;
                text += i + ".";
                if (numeroAux == 1) {
                    numero = numeroAux;
                }
            }
        }
        if (text.isEmpty()) {
            System.out.printf("El número %s es primo!\n", iniNum);
            text = String.valueOf(iniNum);
        }
        buffer.add(String.format("%s=%s", iniNum, text));
        existData=true;

    }

}

y el resultado para 10 números enteros


Enviando número descomposición desde el productor:	1007666687
Enviando número descomposición desde el productor:	233955388
Enviando número descomposición desde el productor:	403028651
Enviando número descomposición desde el productor:	1405658987
Enviando número descomposición desde el productor:	809322159
Enviando número descomposición desde el productor:	263332588
Enviando número descomposición desde el productor:	1552584352
Enviando número descomposición desde el productor:	1342709543
Datos obtenidos desde el consumidor.Resultado:		1007666687=17.31.43.53.839.
Datos obtenidos desde el consumidor.Resultado:		1342709543=7.191815649.
Datos obtenidos desde el consumidor.Resultado:		1552584352=2.2.2.2.2.11.89.49559.
Datos obtenidos desde el consumidor.Resultado:		263332588=2.2.487.135181.
Datos obtenidos desde el consumidor.Resultado:		809322159=3.113.733.3257.
Datos obtenidos desde el consumidor.Resultado:		403028651=67.6015353.
Datos obtenidos desde el consumidor.Resultado:		233955388=2.2.31.443.4259.
Datos obtenidos desde el consumidor.Resultado:		1405658987=127.199.55619.

Saludos

Descomposición factorial con hilos I

Descomposición factorial con hilos I

Un ejemplo de aprovechamiento de recursos sobre procesos penosos en los que ponemos el pc a prueba, puede ser la descomposición de números grandes en factores primos. En este ejemplo sobre la plataforma Java, se descomponen números del tipo Long con un método estándar (no muy eficiente) con una clase que implementa la Interfaz Runnable. A la clase le pasamos un número como parámetro y otro de identificador.Si creamos varios hilos, cada uno descomponiendo un número grande, aprovechará los distintos núcleos para el cálculo. Este es el resultado para números enteros pequeños mostrando el número de hilos vivos.

INICIO Hilo nº0-> Descomposición de 1763458
INICIO Hilo nº2-> Descomposición de 882375341
INICIO Hilo nº3-> Descomposición de 396209470
INICIO Hilo nº1-> Descomposición de 1633289887
Hilo nº 0-> Descomponiendo 1763458. Nº iteraciones: 1
Hilo nº 2-> Descomponiendo 882375341. Nº iteraciones: 96
Hilo nº 3-> Descomponiendo 396209470. Nº iteraciones: 1
Hilo nº 3-> Descomponiendo 198104735. Nº iteraciones: 4
Hilo nº 3-> Descomponiendo 39620947. Nº iteraciones: 18
Hilo nº 3-> Descomponiendo 2085313. Nº iteraciones: 210
Hilo nº 1-> Descomponiendo 1633289887. Nº iteraciones: 66
Hilo nº 1-> Descomponiendo 24377461. Nº iteraciones: 100
Hilo nº 3-> Descomponiendo 9883. Nº iteraciones: 9882
FIN Hilo nº 3-> 396209470 = 2*5*19*211*9883*. Nº iteraciones: 9882
Quedan 3 hilos vivos
Hilo nº 2-> Descomponiendo 9096653. Nº iteraciones: 1810
Hilo nº 2-> Descomponiendo 5023. Nº iteraciones: 5022
FIN Hilo nº 2-> 882375341 = 97*1811*5023*. Nº iteraciones: 5022
Quedan 2 hilos vivos
Hilo nº 1-> Descomponiendo 241361. Nº iteraciones: 241360
FIN Hilo nº 1-> 1633289887 = 67*101*241361*. Nº iteraciones: 241360
Quedan 1 hilos vivos
Hilo nº 0-> Descomponiendo 881729. Nº iteraciones: 881728
FIN Hilo nº 0-> 1763458 = 2*881729*. Nº iteraciones: 881728
Quedan 0 hilos vivos

Y el código de las clases…

Clase Main

package Descompositor;

import java.util.Random;

// <editor-fold defaultstate="collapsed" desc="Cabecera de clase">
/******************************************************
 *  @author:    Joaquín Martínez Rus (c) 2017
 *  @version:   1.0
 *  File:       Main.java
 *  Created:    29/11/2017
 *  Project:    PSP. Ejemplo de descomposición multihilo.
 *  Comments:
 *******************************************************/
// </editor-fold>
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        for (int i = 0; i < 5; i++) {
            Descomposicion d=new Descomposicion(Math.abs(new Random().nextLong()),i);
            Thread hilo=new Thread(d);
            hilo.start();
        }
    }
}

y la clase encargada de la descomposición

package Descompositor;
import java.util.Date;
// <editor-fold defaultstate="collapsed" desc="Cabecera de clase">
/******************************************************
 *  @author:    Joaquín Martínez Rus (c) 2017
 *  @version:   1.0
 *  File:       Descomposicion.java
 *  Created:    29/11/2017
 *  Project:    PSP. Ejemplo de descomposición multihilo.
 *  Comments:
 *******************************************************/
// </editor-fold>
public class Descomposicion implements Runnable{

    public Descomposicion(long n, int j){
        this.name=j;
        this.number=n;
        Descomposicion.instanciasVivas++;
    }

    public static int instanciasVivas;
    int name;
    long number;

    @Override
    public void run() {
        descomponer(number, name);
    }

    void descomponer(long numero, int j){
        // Cálculos y resultados

        long iniNum=numero;
        long numeroAux = numero;
        long n=0;
        int nn=0;

        System.out.printf("INICIO Hilo nº%s-> Descomposición de %s\n" , j, numeroAux);
        String text="";
        String puntos=".";

        for (long i = 2; i 1000000000) {
                nn++;
                String cadena="Hilo Nº %s-> Seguimos calculando para %s...\n";
                if (nn>2) {
                    if (text.isEmpty()) {
                        cadena = "Hilo Nº %s-> parece que el número %s es primo...\n";
                    }
                    else{
                        cadena ="Hilo Nº %s-> No es primo y seguimos calculando para %s...\n";
                        nn=0;
                    }
                }
                System.out.printf(cadena, j, numeroAux);
                n=0;

            }
            // DESCOMPOSICIÓN
            while (numeroAux % i == 0) {
                System.out.printf("Hilo nº %s-> Descomponiendo %s. Nº iteraciones: %s\n",j, numeroAux, n);
                numeroAux /= i;
                text += i + "*";
                if (numeroAux == 1) {
                    numero=numeroAux;
                }
            }
        }
        if (text.isEmpty()){
            System.out.printf("El número %s es primo!\n",iniNum);
            text = String.valueOf(iniNum);
        }
        System.out.printf("FIN Hilo nº %s-> %s = %s. Nº iteraciones: %s\n",j, iniNum, text, n);

        Descomposicion.instanciasVivas--;
        System.out.printf("Quedan %s hilos vivos\n",Descomposicion.instanciasVivas);

    }
}

Os adjunto el proyecto de NetBeans.

Saludos

 

Atajos en Android Studio

Atajos en Android Studio

Como no iba a ser menos, Android Studio también tiene algunos atajos o métodos abreviados para simplificar la escritura de código y he aquí algunos ejemplos útiles.

¿Cuáles son estas abreviaturas? Pues si pulsamos CTRL + J nos muestra en una lista todos ellas.
Pulsando por ejemplo it y CTRL + J, mostraría lo siguiente
abrev01
y escribiendo st + TAB escribe String
Si declaramos por ejemplo un array y luego itar + TAB se genera el siguiente código

String [] array=new String[3];
for (int i = 0; i < array.length; i++) {
       String s = array[i];                    
}

Hay muchas abreviaturas, pero por otra parte, existen combinaciones de teclas y a mi personalmente, me gustan las siguientes:

Cuando vamos a hacer un cast, escribimos el paréntesis y CTRL + MAYUSC + SPC y se completa automáticamente

String a=( CTRL + MAYUSC + SPC → String a=(String)
CTRL + SPC nos muestra las sugerencias en el contexto actual. Si escribimos nu…abrev02

CTRL + P entre los paréntesis donde se albergan los parámetros de un método, nos muestra una ayuda de los parámetros

abrev03

CTRL + / o CTRL + MAYUSC + / comenta mediante // o /**/ respectivamente las líneas

ALT + CTRL + L formatea el código

CTRL + click sobre un objeto o método, navega hasta la declaración de este

CTRL + MAYUSC + RETROCESO, navega hasta el último lugar donde realizamos la última edición.

…  y muchos más.