Estoy estudiando los threads o hilos en Java, y hay algo que me trae de cabeza con esto. Ojalá puedan echarme una mano con esto. Sé que existen varias formas de sincronizarlos, por ejemplo utilizando join(), synchronized, wait() y notify(), ReentrantLock(), etc. Sin embargo éstos no me están ayudando.
PROBLEMA. Tengo un hilo1 que recupera información de una base de datos y la guarda en una serie de variables. Hasta aquí todo va perfecto. El problema es que no logro hacer que después y sólo después que terminó de ejecutarse este hilo1, se ejecute otro código encargado de utilizar esas variables.
Código Java:
Ver original
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Hilo1 hilo1 = new Hilo1(MainActivity.this); hilo1.setName("Hilo1"); hilo1.start(); rv = (RecyclerView) findViewById(R.id.rv); rv.setLayoutManager(new LinearLayoutManager(this)); rv.setAdapter(new RecyclerViewAdapter(MainActivity.this, paginador.generatePage(paginaActual))); // Línea ALFA }
Como se ve en el código de aquí arriba, estoy ejecutando el hilo1, y abajo, en la última línea del onCreate(), se ejecuta la línea encargada de manipular la UI (metiendo información a un RecyclerView). A esta línea la llamaré ALFA (por economía del lenguaje). Alfa llama a un método generatePage() que utiliza las variables que comentaba antes.
Claramente alfa se ejecuta dentro del hilo main, el cual no espera a que termine el hilo1. Es decir, ambos hilos son concurrentes. Por tanto, antes que termine el hilo1 ya se ejecutó alfa.
La pregunta es: ¿cómo lograr que alfa se ejecute después y sólo después que muera el hilo1?
La primera idea que se me ocurrió fue meter alfa dentro de un hilo2, y así lograr fácilmente que el hilo2 se ejecute después del hilo1 mediante join(). Lo hice y me encontré con 2 problemas: A) Resulta que por defecto los threads en Java no pueden modificar la UI, y B) Encontré la forma de manipular la UI desde un thread, sin embargo poco importa que se pueda hacer esto, ya que esa manipulación se ejecuta desde el hilo main, no desde el hilo2 (lo sé porque Thread.currentThread().getName() así lo indica), así que de nada sirve que meta alfa dentro de un hilo2, que sería este:
Código Java:
Ver original
public void run() { try { hilo1.join(); // Este join espera a que muera el hilo1, y sólo después ejecuté el código de este hilo2 } e.printStackTrace(); } // Así es como manipulo la UI desde el hilo2: Handler handler = new Handler(Looper.getMainLooper()); @Override public void run() { // El contenido del run() de este handler NO se ejecuta dentro del hilo2 sino dentro del hilo main rv.setAdapter(new RecyclerViewAdapter(contexto, paginador.generatePage(paginaActual))); // Aquí manipulo la UI } }); }
Por todo lo dicho, la única forma que se me ocurre de lograr que alfa se ejecute después que terminó/murió el hilo1, es haciendo un sleep(2000); entre el hilo1 y alfa. Esta solución me parece ser la más sucia y poco elegante que pudiera existir. Sin embargo lo pregunto, por si acaso resulta que no es tan mala solución.
Saludos,