Java - Usar "static"... ¿mala práctica?

 
Vista:
sin imagen de perfil
Val: 4
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

Usar "static"... ¿mala práctica?

Publicado por Fco. Javier (3 intervenciones) el 06/05/2018 14:27:07
Usar "static"... ¿mala práctica?
"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?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
 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) {}
          }
     }
}
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Usar "static"... ¿mala práctica?

Publicado por Tom (1589 intervenciones) el 06/05/2018 21:21:56
Lo primero es que el objeto que uses como "bloqueo" no tiene por qué ser estático. Generalmente se usa así por comodidad, no por otra cosa.
Lo segundo es que en java ... una clase es un objeto (Class), así que las objeciones de tu profesor, quizás sean un poco vagas.
Por lo demás yo no creo que haya ningún problema en usar objetos estáticos cuando sea necesario ... ¿ para qué querrías manejar 20 referencias a un objeto cuya vida es la misma que la de tu aplicación, si lo puedes usar como estático ?

Puedes probar algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private synchronized void consumir() {
    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...
         this.notifyAll(); //Despertar a el COCINERO que esperaba (abrir cerrojo, dejar pasar)
 
         try {
              this.wait(); //Dormir al consumidor (hasta que lo despierten)
         } catch (InterruptedException e) {
              e.printStackTrace();
         }
    }
}

O locks :
http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
Imágen de perfil de Pedro
Val: 316
Bronce
Ha aumentado 1 puesto en Java (en relación al último mes)
Gráfica de Java

Usar "static"... ¿mala práctica?

Publicado por Pedro (102 intervenciones) el 06/05/2018 22:08:23
#Tom eres admirable ojalá algún día llegue a tu nivel de Java.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Rafael Angel
Val: 480
Bronce
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Usar "static"... ¿mala práctica?

Publicado por Rafael Angel (4 intervenciones) el 07/05/2018 16:51:38
Crear una clase abstract que puedan heredar las demás clases del proyecto y se pasarían unas a otras los valores en forma gerquica.
Yo lo hago así porque no me gusta static, es un estigma de cuando no existía orientación a objetos, de hecho muchos lenguajes aún usan cosas similares.
En unos días subiré un proyecto donde se ve el uso gerarquico de un objeto heredado.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar