Foros del Web » Programación para mayores de 30 ;) » Java »

[SOLUCIONADO] ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un thread Java?

Estas en el tema de ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un thread Java? en el foro de Java en Foros del Web. Hola, muchachos! Cada vez entiendo un poquito mejor cómo funciona el tema de los hilos (threads) en Java. Sin embargo sigo teniendo problemas. Ojalá puedan ...
  #1 (permalink)  
Antiguo 05/04/2020, 19:56
Avatar de berkeleyPunk  
Fecha de Ingreso: febrero-2013
Ubicación: México :C
Mensajes: 565
Antigüedad: 11 años, 9 meses
Puntos: 22
Pregunta ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un thread Java?

Hola, muchachos! Cada vez entiendo un poquito mejor cómo funciona el tema de los hilos (threads) en Java. Sin embargo sigo teniendo problemas. Ojalá puedan echarme una mano con esto que comento a continuación.

Pongo aquí minimizado mi código. No quiero poner el código entero de las 2 clases que menciono, porque estoy seguro que les dará flojera leerlo, y porque me parece que no hace falta ponerlo aquí para entender mi problema.

En los comentarios hallados dentro de este código, explico todo, incluyendo mi duda.

Código Java:
Ver original
  1. public class MainActivity extends AppCompatActivity {
  2.  
  3.     public static int MI_VARIABLE;
  4.  
  5.     @Override
  6.     protected void onCreate(Bundle savedInstanceState) {
  7.         super.onCreate(savedInstanceState);
  8.         setContentView(R.layout.activity_main);
  9.  
  10.         // A esta altura, el log indica que la variable MI_VARIABLE es igual a 0 (cero). Todo bien aquí.
  11.         Log.println(Log.INFO, "infor", "MI_VARIABLE: "+MI_VARIABLE);
  12.  
  13.         // Instancio e inicio un primer hilo llamado "hilo1" de una clase llamada "MiClase". La clase "MiClase" importa MI_VARIABLE así: import static com.example.miproyecto.MainActivity.MI_VARIABLE, y luego asigna el valor correspondiente a MI_VARIABLE (digamos 7). Todo bien hasta aquí.
  14.         List params1 = new ArrayList();
  15.         MiClase hilo1 = new MiClase(params1);
  16.         hilo1.setName("Hilo1");
  17.         hilo1.start();
  18.  
  19.         // Instancio e inicio un segundo hilo llamado "hilo2" de la misma clase "MiClase". Gracias al parámetro que le paso al constructor de "MiClase", este hilo2 sólo se ejecuta hasta que termine/muera el hilo1; por lo cual, cuando por fin se ejecuta el hilo2, MI_VARIABLE ya es mayor a 0 (cero). Todo bien hasta aquí.
  20.         List params2 = new ArrayList();
  21.         params2.add(hilo1);
  22.         MiClase hilo2 = new MiClase(params2);
  23.         hilo2.setName("Hilo2");
  24.         hilo2.start();
  25.  
  26.         // El problema está aquí: la condición del WHILE siempre se cumple, por lo cual la consola imprime indefinidamente: "MI_VARIABLE es igual a 0". ¿Por qué pasa esto si casi inmediatamente después de iniciada la app, MI_VARIABLE ya es mayor a 0? ¿Por qué el WHILE nunca se entera de que esto es así? ¿Qué puedo hacer para que el MainActivity.java haga algo en caso que MI_VARIABLE siga o no siga siendo igual a 0?
  27.         while(MI_VARIABLE==0) {
  28.             Log.println(Log.INFO, "infor", "MI_VARIABLE es igual a 0");
  29.         }
  30.     }
  31. }

Saludos!

Última edición por berkeleyPunk; 05/04/2020 a las 20:07
  #2 (permalink)  
Antiguo 06/04/2020, 15:57
 
Fecha de Ingreso: abril-2011
Mensajes: 170
Antigüedad: 13 años, 7 meses
Puntos: 68
Respuesta: ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un t

Para que los cambios en la variable afecten a todos los hilos (incluido el hilo principal), debes marcar dicha variable como volatile:

Código Java:
Ver original
  1. public static volatile int MI_VARIABLE;

Última edición por prueba230683; 06/04/2020 a las 16:03
  #3 (permalink)  
Antiguo 07/04/2020, 21:01
Avatar de berkeleyPunk  
Fecha de Ingreso: febrero-2013
Ubicación: México :C
Mensajes: 565
Antigüedad: 11 años, 9 meses
Puntos: 22
Respuesta: ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un t

Muchas gracias por responder. Lamentablemente no me funciona! ¿Tienes alguna otra idea de por dónde puede estar el problema?
  #4 (permalink)  
Antiguo 07/04/2020, 21:03
Avatar de berkeleyPunk  
Fecha de Ingreso: febrero-2013
Ubicación: México :C
Mensajes: 565
Antigüedad: 11 años, 9 meses
Puntos: 22
Respuesta: ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un t

Cita:
Iniciado por prueba230683 Ver Mensaje
Para que los cambios en la variable afecten a todos los hilos (incluido el hilo principal), debes marcar dicha variable como volatile:

Código Java:
Ver original
  1. public static volatile int MI_VARIABLE;
Muchas gracias por responder. Lamentablemente no me funciona! ¿Tienes alguna otra idea de por dónde puede estar el problema?
  #5 (permalink)  
Antiguo 08/04/2020, 08:21
 
Fecha de Ingreso: abril-2011
Mensajes: 170
Antigüedad: 13 años, 7 meses
Puntos: 68
Respuesta: ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un t

Crea una clase aparte que contenga la propiedad que quieres manipular entre varios hilos:

Código Java:
Ver original
  1. public class Objeto {
  2.     public volatile int MI_VARIABLE;
  3. }

Y en tu código pasas una instancia de dicho objeto (con el valor de obj.MI_VARIABLE que quieras):

Código Java:
Ver original
  1. public class MainActivity extends AppCompatActivity {
  2.  
  3.     @Override
  4.     protected void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         setContentView(R.layout.activity_main);
  7.        
  8.         Objeto obj = new Objeto();
  9.         obj.MI_VARIABLE = 0; // inicialmente, la establecemos a 0
  10.  
  11.         Log.println(Log.INFO, "infor", "MI_VARIABLE: " + obj.MI_VARIABLE);
  12.  
  13.         List params1 = new ArrayList();
  14.         MiClase hilo1 = new MiClase(params1, obj); // pasamos el objeto
  15.         hilo1.setName("Hilo1");
  16.         hilo1.start();
  17.  
  18.         List params2 = new ArrayList();
  19.         params2.add(hilo1);
  20.         MiClase hilo2 = new MiClase(params2, obj); // pasamos el objeto
  21.         hilo2.setName("Hilo2");
  22.         hilo2.start();
  23.        
  24.         while(obj.MI_VARIABLE == 0) {
  25.             Log.println(Log.INFO, "infor", "MI_VARIABLE es igual a 0");
  26.         }
  27.     }
  28. }

Luego desde MiClase, en lugar de importar (import static com.example.miproyecto.MainActivity.MI_VARIABLE), directamente recibes el objeto y modificas la propiedad MI_VARIABLE de dicho objeto (obj.MI_VARIABLE = 123123).

Código Java:
Ver original
  1. public class MiClase {
  2.     public MiClase(List lista, Objeto obj){
  3.        // ...
  4.        obj.MI_VARIABLE = 123123; // esto se debería reflejar en todos los hilos
  5.        // ...
  6.     }
  7. }

Última edición por prueba230683; 08/04/2020 a las 08:59
  #6 (permalink)  
Antiguo 18/04/2020, 10:27
Avatar de berkeleyPunk  
Fecha de Ingreso: febrero-2013
Ubicación: México :C
Mensajes: 565
Antigüedad: 11 años, 9 meses
Puntos: 22
De acuerdo Respuesta: ¿Por qué MainActivity nunca se entera que mi variable fue alterada en un t

Cita:
Iniciado por prueba230683 Ver Mensaje
Crea una clase aparte que contenga la propiedad que quieres manipular entre varios hilos...
Gracias, prueba230683, por tus sugerencias. De hecho finalmente logré solucionar este problema. Por lo que estuve viendo, la respuesta inicial que sugeriste era buena opción y probablemente funciona en la mayoría de los casos, pero no cuando MI_VARIABLE se gestiona con Volley, como es mi caso. Entonces, para solucionar el problema, el código que se encargaba de leer MI_VARIABLE, simplemente lo metí en una AsyncTask y eso solucionó el problema.
De cualquier modo, ya tengo esta solución que aportas aquí, y en el futuro si me vuelve a suceder este asunto, la probaré. Gracias nuevamente!

Etiquetas: fue, nunca, variable
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 16:18.