elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java
| | | |-+  Usar "static" en Concurrencia. ¿mala práctica?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Usar "static" en Concurrencia. ¿mala práctica?  (Leído 3,485 veces)
fjlopezc17

Desconectado Desconectado

Mensajes: 5


Ver Perfil
Usar "static" en Concurrencia. ¿mala práctica?
« en: 6 Mayo 2018, 16:11 pm »

"Esta cuestión es un tema que se trata mucho en los foros. A mí no me gusta nada la declaración static, ya que implica por un lado que puedes usar métodos de un a clase sin necesidad de declarar objetos de la propia clase, o bien la compartición directa de atributos para todas las instancias de una clase. Ambos comportamientos, a mi entender son un mal uso de la programación orientada a objetos, pero son permitidos en JAVA (como muchas otras cosas)." Mi profesor.
¿Qué opináis sobre nuestro amigo "static"?

Independientemente de las discrepancias que cada uno pueda tener con esta declaración, me encuentro en el siguiente caso:
Si habéis tratado con Java Concurrente, seguramente sabréis que es muy usual utilizar el ejemplo del "Cocinero y Cliente"/"Productor y consumidor", etc. para ejemplificar el uso práctico de la concurrencia en Java.

El siguiente código que voy a mostraros ahora utiliza la variable entera static "tarta" y un 'lock' para el bloque synchronized también static. Creo que la pregunta es evidente, ¿si el uso de "static" es, supuestamente, y para algunos, una mala práctica, cómo podríamos resola declaración static?una forma alternativa a usar la declaración static?
Código:
/*

 CONSUMIDOR:

 - Si hay tarta = Me como una

 - Si NO ... = Despertar COCINERO, dormir CONSUMIDOR.

 COCINERO:

 - Me duermo esperando a que un cliente me llame

 - Si me llama produzco 10 trozos de tarta, me duermo.

 */

public class Principal implements Runnable {

 

     private boolean consumidor;

     private static int tarta=0;

     private static Object lock = new Object();

   

     public Principal(boolean consumidor) {

          this.consumidor=consumidor;

     }

 

     public void run() {

          while(true) {

                if(consumidor) {

                     consumir();

                }else {

                     cocinar();

                }

          }

     }

   

     private void consumir() {

          synchronized(lock) { //Cerrojo

                if(tarta>0) { //SI QUEDAN TARTAS...

                     tarta--; //Comer una tarta

                     System.out.println("Quedan "+tarta+" porciones de tarta.");

                     try {

                          Thread.sleep(1000);

                     } catch (InterruptedException e) {

                          e.printStackTrace();

                     }

                }else { //SI NO QUEDAN TARTAS...

                     lock.notifyAll(); //Despertar a el COCINERO que esperaba (abrir cerrojo, dejar pasar)

                     try {

                          lock.wait(); //Dormir al consumidor (hasta que lo despierten)

                     } catch (InterruptedException e) {

                          e.printStackTrace();

                     }

                }

          }

     }

   

     private void cocinar() {

          synchronized (lock) {

                if(tarta==0) {

                     tarta=10; //Cocinar 10 trozos de tarta

                     System.out.println("Soy el cocinero y quedan "+tarta+" trozos.");

                     lock.notifyAll(); //"¡Chacho! Que las tartas están listas!", Vale tío.

                } try {

                     lock.wait(); //dormir

                }catch(Exception e) {}

          }

     }

   

     public static void main(String[] args) {

          int numHilos = 11;

         

          Thread[] hilo = new Thread[numHilos];

         

          for(int i=0; i<hilo.length; i++) {

                Runnable runnable = null;

               

                if(i !=0) {

                     runnable = new Principal(true);

                }else {

                     runnable = new Principal(false);

                }

               

                hilo[i] = new Thread(runnable);

                hilo[i].start();

          }

         

          for(int i=0; i<hilo.length; i++) {

                try {

                     hilo[i].join();

                }catch(Exception e) {}

          }

     }

}


En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: Usar "static" en Concurrencia. ¿mala práctica?
« Respuesta #1 en: 7 Mayo 2018, 03:26 am »

El uso de "Static", no es mala práctica, la mala práctica resulta de no entenderlo.

Un campo, función, objeto... en definitiva una entidad se debe declarar Static, cuando solo deba existir una única copia para cualquiera que sea el número de instancias que se creen. Y para que esto sea así, ha de requerirse que el campo, función u objeto no retengan... ni dependan de... ningún dato específico de una instancia.

Por ejemplo, al crea una instancia de un punto, cada punto puede tener valores distintos:
 p1.X = 20
 p1.Y = 12
en cambio un punto que sea el origen, puede declararse Static, porque siempre será.
 p.X = 0
 p.Y = 0
Dicho de otro modo, puede proveerse a la clase punto, un método estático, llamado Origen que lo que haga sea precisamente poner a 0 los campos 'X' e 'Y'... o proveer una instancia de un punto con valores 0,0 (para X e Y) y por lo mismo, no hay razón para que cada instancia deba proveer o implementar dicho método... es universal. Cumple el cometido que se le encomienda al modificador 'Static', una sola copia de ese método, vale para satisfacer todas las intancias.

La solución que preguntas pasa por declarar cuando proceda a determinados miembros como de solo lectura o solo escritura, así Tarta, parece que debe ser de solo lectura, no de escritura (desde fuera), o directamente un miembro privado y solo proveer trozos de tarta, y al caso a lo sumo proveer una propiedad "TrozosPorTarta", cuyo valor sea el que se tome internamente cuando deba crearse una nueva tarta.

Lo dicho para un campo, o propiedad, vale para cualquier otra entidad... un método Sort, por ejemplo, tomará un array (del tipo que sea) y lo ordenará, mientras opera con él usará variables internas para mantener el estado de operaciones, pero cuando termine, ese estado se pierde y una nueva llamada restablece el estado a su punto inicial, por ello un método Sort, es un candidato perfecto a ser declarado Static. Nada de una instancia específica queda retenuido en el método Sort, que altere una siguiente llamada al método.

En definitiva, Static, lo que hace es que exista una única copia, de lo que se declare Static, independientemente del número de instancias que existan, ahorrando con ello bastante memoria.


« Última modificación: 7 Mayo 2018, 03:50 am por NEBIRE » En línea

srWhiteSkull


Desconectado Desconectado

Mensajes: 444



Ver Perfil WWW
Re: Usar "static" en Concurrencia. ¿mala práctica?
« Respuesta #2 en: 7 Mayo 2018, 12:58 pm »

"Esta cuestión es un tema que se trata mucho en los foros. A mí no me gusta nada la declaración static, ya que implica por un lado que puedes usar métodos de un a clase sin necesidad de declarar objetos de la propia clase, o bien la compartición directa de atributos para todas las instancias de una clase. Ambos comportamientos, a mi entender son un mal uso de la programación orientada a objetos, pero son permitidos en JAVA (como muchas otras cosas)." Mi profesor.
¿Qué opináis sobre nuestro amigo "static"?

Mi consejo es que si buscas argumentos para rebatir con tú profesor es que no lo hagas(desiste), como estudiante dile que si y asiente con la cabeza, si lo que quieres es aprobar. La triste realidad es que el diseño de un lenguaje de programación no lo crean simples becarios, normalmente se trata de un equipo de señores muy experimentados con muchos títulines y masters del universo.

Los elementos estáticos en la programación no son un invento de Sun Microsystem, ya sobre los sesenta lenguajes como AGOL y el C habían implementado esto y lo veían como algo necesario. Y actualmente en múltiples lenguajes también han introducido la instrucción static (sin ir más lejos en el 2015 se aprobó el EMACS 6 que incluye también esto en la POO).

Tal como te subrayé en la cita es muy probable que sea una opinión personal.

El siguiente código que voy a mostraros ahora utiliza la variable entera static "tarta" y un 'lock' para el bloque synchronized también static. Creo que la pregunta es evidente, ¿si el uso de "static" es, supuestamente, y para algunos, una mala práctica, cómo podríamos resola declaración static?una forma alternativa a usar la declaración static?

No, no es una mala práctica, peeero, lo ideal o recomendable es pasar los elementos que tienes definidos como estáticos, como un elementos compartido vía constructor o método. Ejemplo :

Código:
class Tarta extends Object {
    int tarta=0;
}

...

public class PruebaJava implements Runnable {  
    private boolean consumidor;
    private Tarta lockTarta ;
    
    public PruebaJava(Tarta lockTarta, boolean consumidor) {
        this.lockTarta     = lockTarta;
        this.consumidor    = consumidor;
    }

...

    public static void main(String[] args) {
        int numHilos = 2;
        Tarta tarta = new Tarta(); // elemento compartido
        Thread[] hilo = new Thread[numHilos];        

        for(int i=0; i<hilo.length; i++) {
            Runnable runnable = null;

            if(i !=0) {
                runnable = new PruebaJava(tarta, true); // todas las instancias comparten el mismo elemento
            }else {
                runnable = new PruebaJava(tarta,false); // todas las instancias comparten el mismo elemento
            }

...
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines