SoFunction
Updated on 2025-04-13

Summary of several ways to implement multithreading in Android

1. Basic thread (Thread)

principle

Create and start threads directly through Java's Thread class, suitable for simple asynchronous tasks.

Example

new Thread(new Runnable() {
    @Override
    public void run() {
        // Child threads perform time-consuming tasks (such as network requests)        // Note: The UI cannot be updated directly here!        runOnUiThread(() -> {
            ("Task Complete"); // Switch to main thread update UI        });
    }
}).start();
 
// Kotlin simplified writingThread {
    // Child thread task    runOnUiThread {  = "Task Complete" }
}.start()

shortcoming

Manual management is complicated: it is difficult to control when there are too many threads.

Unable to update UI directly: The main thread must be switched back to the main thread through runOnUiThread or Handler.

2. Handler and Looper

principle

Inter-thread communication is achieved through Handler and Looper, suitable for scenarios where UI needs to be updated frequently on the main thread.

Example

// Main thread creates HandlerHandler mainHandler = new Handler(());
 
new Thread(() -> {
    // The child thread executes the task    (() -> {
        ("Update the UI through Handler");
    });
}).start();

Extension: child thread creates message loop

// Child thread initialization Looperclass WorkerThread extends Thread {
    private Handler workerHandler;
 
    @Override
    public void run() {
        (); // Create Looper        workerHandler = new Handler(()) {
            @Override
            public void handleMessage(Message msg) {
                // Process the messages received by the child thread            }
        };
        (); // Start message loop    }
}

advantage

Flexible control of thread communication: supports delayed message and message queue management.

Main thread safety update UI.

3. AsyncTask (deprecated, only for understanding)

principle

Asynchronous task tools provided by Android in the early days encapsulate thread switching logic internally.

Example

private class MyAsyncTask extends AsyncTask<Void, Integer, String> {
    @Override
    protected String doInBackground(Void... voids) {
        // Child threads perform time-consuming tasks        publishProgress(50); // Update progress        return "result";
    }
 
    @Override
    protected void onProgressUpdate(Integer... values) {
        // Main thread update progress bar        (values[0]);
    }
 
    @Override
    protected void onPostExecute(String result) {
        // Main thread processing results        (result);
    }
}
 
// Start the tasknew MyAsyncTask().execute();

shortcoming

Memory leak risk: If AsyncTask holds an Activity reference, it may not be recycled.

API 30+ Deprecated: Coroutines or ExecutorService are recommended.

4. ExecutorService (thread pool)

principle

The thread pool management provided by the Java concurrency framework is suitable for scenarios where the number of concurrency needs to be controlled.

Example

// Create a fixed-size thread poolExecutorService executor = (4);
 
(() -> {
    // The child thread executes the task    runOnUiThread(() -> ("Task Complete"));
});
 
// Close the thread pool (usually called in onDestroy)();

advantage

Resource reuse: Avoid the overhead of frequent creation/destruction of threads.

Task Queue Management: Supports submission of Runnable or Callable tasks.

5. IntentService (deprecated, WorkManager is recommended)

principle

Inherited from Service, it handles asynchronous tasks internally through HandlerThread, which is suitable for the background to execute independent tasks.

Example

public class MyIntentService extends IntentService {
    public MyIntentService() {
        super("MyIntentService");
    }
 
    @Override
    protected void onHandleIntent(Intent intent) {
        // The child thread executes tasks (such as file download)        // No need to stop manually, it will be automatically destroyed after the task is completed    }
}
 
// Start the serviceIntent intent = new Intent(context, );
startService(intent);

shortcoming

Android 8.0+ restricted background services: You need to use WorkManager or JobScheduler instead.

6. Kotlin coroutines (Coroutines, modern recommended solutions)

principle

Non-blocking asynchronous operations are implemented through Suspend Functions, simplifying callback hell.

Example

// Use coroutines in ViewModelclass MyViewModel : ViewModel() {
    fun fetchData() {
        () { // Switch to IO thread            val result = () // Network request            withContext() {    // Switch back to main thread                 = result
            }
        }
    }
}
 
// Concurrent task processing {
    val deferred1 = async { fetchData1() } // Start asynchronous task 1    val deferred2 = async { fetchData2() } // Start asynchronous task 2    val result1 = ()        // Wait for task 1 to complete    val result2 = ()        // Wait for task 2 to complete    showResult(result1 + result2)          // Merge results}

advantage

  • Concise code: use synchronous writing to implement asynchronous logic.
  • Lifecycle Awareness: Automatically bind to the ViewModel or Activity lifecycle.
  • Flexible scheduling: Specify threads through /IO/Default.

7. HandlerThread

principle

Combined with Thread and Looper, it is suitable for child thread tasks that require long-running.

Example

HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
();
 
Handler handler = new Handler(());
(() -> {
    // Execute tasks in HandlerThread});
 
// Release resources during destruction();

Comparative summary

Way Applicable scenarios advantage shortcoming
Thread Simple asynchronous tasks Direct and easy to use Manual management is complicated and cannot be updated directly.
Handler Main thread communication Flexible control of message queues Code redundancy
AsyncTask Old project simple task (deprecated) Automatic thread switching Memory leak risk, API abandonment
Executor Thread pool management Resource reuse, task queue management Need to manually switch main thread
IntentService Background Independent Task (deprecated) Automatic destruction Due to system limitations, the alternative is better
Coroutine Modern asynchronous programming Concise code, life cycle perception Need to learn Kotlin grammar
HandlerThread Child thread tasks that require Looper Bring your own message loop Need to exit manually

Best Practice Recommendations

Simple task: Use Thread + Handler or runOnUiThread.

Complex concurrency: preferred coroutines (with viewModelScope or lifecycleScope).

Thread pool management: Use ExecutorService to control the number of concurrency.

Backend persistent tasks: Use WorkManager (compatible with different API versions).

By rationally choosing a multi-threading solution, the application's response speed and user experience can be significantly improved, while avoiding ANR (Application Not Responding) problems.

This is the article about several ways to implement multi-threading in Android. For more related content on Android implementation, please search for my previous articles or continue browsing the related articles below. I hope you will support me in the future!