What are Threads in Android with Example?

Last Updated : 23 Jul, 2025

In Android, a thread is a separate path of execution. By default, your app runs on a single main thread (UI thread). All user interactions, UI updates, and view rendering happen on this main thread. If you perform long-running operations (like network requests, database access, or heavy computation) on the main thread, the app may become unresponsive and even crash with an ANR (Application Not Responding) error. To avoid this, such operations should be offloaded to background (worker) threads, keeping the UI thread free to handle user interaction.

However, they are part of the same application process and share the same memory space. In Java and Kotlin, the Thread class and coroutines can be used to create and manage threads.

Java
Thread thread = new Thread(new Runnable() {
    @Override public void run() {
        // code to run in background thread
    }
});
thread.start();
Kotlin
GlobalScope.launch {
    // code to run in background thread
}

Note: It's recommended to use coroutines in Kotlin instead of Thread, as they are more lightweight and easier to manage.


Code Snippet of a function that uses coroutines to perform a network request in the background, and updates the UI with the result:

fun doNetworkRequest() = GlobalScope.launch(Dispatchers.Main) {
val result = withContext(Dispatchers.IO) {
// perform network request
}
// update UI with the result
}

There are different types of threads in Android, each with its own use cases:

  • The main thread, also known as the UI thread, is responsible for handling all UI updates and user interactions. Any code that updates the UI or interacts with the user should be run on the main thread.
  • Worker threads are used for background tasks that should not block the main thread, such as network requests, database operations, and image processing.
  • AsyncTask is a helper class that allows you to perform background tasks and update the UI from the same thread. However, it has some limitations and it's recommended to use coroutines or other libraries for more complex tasks.
  • Services are used for tasks that should continue running even when the app is not visible, such as playing music or downloading files.
  • In addition to the above, there are other types of threading mechanisms available in android such as IntentService, JobIntentService, Service, JobScheduler, and AlarmManager.

It's important to choose the right threading mechanism for your task to ensure optimal performance and avoid threading issues. It's also important to test your app thoroughly on different devices and configurations to ensure that it behaves correctly and does not crash due to threading issues.


Step by Step Implementation

Step 1: Create a New Project in Android Studio

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.

The code for that has been given in both Java and Kotlin Programming Language for Android.

Step 2: Add Dependencies (Kotlin)

To use coroutines in Kotlin, we need to add the following dependencies in Gradle Scripts > build.gradle.kts (Module :app)

dependencies {
...
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}

Step 3: Working with the XML Files

Next, go to the activity_main.xml file, which represents the UI of the project. Below is the code for the activity_main.xml file. Comments are added inside the code to understand the code in more detail.

activity_main.xml:

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <!-- Display the result text -->
    <TextView
        android:id="@+id/result_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Result will appear here"
        android:textSize="25sp" />

    <!-- Start button -->
    <Button
        android:id="@+id/start_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Start" />

</LinearLayout>


Step 3: Working with the MainActivity File

Go to the MainActivity File and refer to the following code. Below is the code for the MainActivity File. Comments are added inside the code to understand the code in more detail.

Java
package org.geeksforgeeks.demo;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView resultTextView;
    private Button startButton;
    // To update UI from background thread
    private Handler handler = new Handler(Looper.getMainLooper()); 

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

        resultTextView = findViewById(R.id.result_text_view);
        startButton = findViewById(R.id.start_button);

        startButton.setOnClickListener(view -> {
            resultTextView.setText("Processing...");
            // Creating a new thread
            new Thread(() -> {
                try {
                    Thread.sleep(3000); // Simulate long task
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // Update UI using handler
                handler.post(() -> resultTextView.setText("Task Completed"));
            }).start();
        });
    }
}
Kotlin
package org.geeksforgeeks.demo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    private lateinit var resultTextView: TextView
    private lateinit var startButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        resultTextView = findViewById(R.id.result_text_view)
        startButton = findViewById(R.id.start_button)

        startButton.setOnClickListener {
            // Launch a coroutine on the Main (UI) thread
            CoroutineScope(Dispatchers.Main).launch {
                resultTextView.text = "Processing..."
                val result = withContext(Dispatchers.IO) {
                    // Background task simulation
                    delay(3000)
                    "Task Completed"
                }
                resultTextView.text = result // Update UI
            }
        }
    }
}

Output:


Comment

Explore