Como programar un Thread Pool en Android con Android Studio y Java como lenguaje de programación

como funciona un thread pool en android

Un Thread Pool en terminos generales es una coleccion de hilos que siempre van a estar a la espera de tareas a ejecutar.

El echo de que los hilos están creados desde el inicio de la aplicación implica que las tareas se van a ejecutar más rápido, ya que no perderemos tiempo, ni recursos a la hora de crear e iniciar los Threads (hilos).

Programar un Thread Pool en Android con Android Studio es relativamente fácil.

Primero veamos la definicion de un Thread Pool.

¿Que es un Thread Pool?

Un grupo de hilos (Thread Pool) es una colección de hilos que pueden ejecutar varias instancias de una tarea en paralelo. Debido a que las tareas se ejecutan en paralelo, es posible que desee asegurarse de que su código sea seguro para los hilos. Un grupo de subprocesos aborda dos problemas principales:

  • Rendimiento mejorado al ejecutar una gran colección de tareas asincrónicas debido a una reducción de la sobrecarga por tarea.
  • Un medio para delimitar y administrar recursos (incluidos subprocesos) al ejecutar una colección de tareas.

Veamos una imagen sobre como es su funcionamiento en términos generales.

como funciona un thread pool en android

En la parte superior tenemos una cola con todas las tareas pendientes por realizar, en el medio tenemos nuestro Thread Pool con un tamaño de 6, una vez procesadas esas tareas pasan a la cola de tareas completadas.

¿Cuando usar un Thread Pool?

Un Thread Pool se usa para hacer una aplicación más rápida, para nuestro caso en Android, ya que por ejemplo si necesitamos ejecutar 100 operaciones, lo que ocurriría es que se crea un hilo que va secuencialmente ejecutando esas 100 operaciones. Al tener un Thread Pool, podemos definir por ejemplo un tamaño de 10 threads, así al momento de enviar las 100 operaciones a ejecutar, en lugar de ser ejecutadas secuencialmente una a una, el pool ira ejecutando de a 10 tareas, lo cual implica que seria 10 veces más rápido.

Implementar un Thread Pool en Android

La forma más fácil es usar Android Studio, pues permite programar a nivel nativo una aplicación en Android. Como lenguaje de programación decidí usar Java porque trae algunas librerías que permiten una codificación bastante simple, pues la verdad, desconozco si en Kotlin también se pueda hacer.

Como saben, Android Studio maneja un sistema Vista Control, el control por lo regular esta programado en Java o Kotlin y la vista en xml.

Codigo de la clase Java

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {


    /*
     * Gets the number of available cores
     * (not always the same as the maximum number of cores)
     */
    private static int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();

    // Sets the amount of time an idle thread waits before terminating
    private static final int KEEP_ALIVE_TIME = 1000;

    // Sets the Time Unit to Milliseconds
    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.MILLISECONDS;

    // Used to update UI with work progress
    private int count = 0;

    // This is the runnable task that we will run 100 times
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // Do some work that takes 50 milliseconds
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // Update the UI with progress
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    count++;
                    String msg = count < 100 ? "working " : "done ";
                    updateStatus(msg + count);
                }
            });

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // button click - performs work on a single thread
    public void buttonClickSingleThread(View view) {

        count = 0;
        Executor mSingleThreadExecutor = Executors.newSingleThreadExecutor();

        for (int i = 0; i < 100; i++) {
            mSingleThreadExecutor.execute(runnable);
        }
    }

    // button click - performs work using a thread pool
    public void buttonClickThreadPool(View view) {
        count = 0;
        ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(
                NUMBER_OF_CORES + 5,   // Initial pool size
                NUMBER_OF_CORES + 8,   // Max pool size
                KEEP_ALIVE_TIME,       // Time idle thread waits before terminating
                KEEP_ALIVE_TIME_UNIT,  // Sets the Time Unit for KEEP_ALIVE_TIME
                new LinkedBlockingDeque<Runnable>());  // Work Queue

        for (int i = 0; i < 100; i++) {

            mThreadPoolExecutor.execute(runnable);
        }
    }

    private void updateStatus(String msg) {
        ((TextView) findViewById(R.id.text)).setText(msg);
    }
}

Codigo xml de la vista o interfaz

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/text"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/app_name" />

        <Button
            android:id="@+id/singleButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="buttonClickSingleThread"
            android:text="Single Thread" />

        <Button
            android:id="@+id/poolButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="buttonClickThreadPool"
            android:text="Thread Pool" />

    </LinearLayout>

</ScrollView>

Si te da pereza o no te funciona pegando el código antes mencionado, te dejo el link del proyecto en GitHub, solo debes clonarlo o descargarlo e importarlo a tu Android Studio.

Conclusiones

Hemos visto la teoría general sobre Thread Pools, asi como también un ejemplo de cuando y como se debe usar.

La velocidad de la aplicación entre un solo hilo vs Thread Pool va a variar dependiendo la cantidad de procesadores que tenga el teléfono móvil o emulador donde se ejecute la aplicación, pero siempre va a ser mas rapido el método Thread Pool.

Deja un comentario