Android Multithreading Java Samples

Android Java multithreading examples including thread creation, synchronization with locks, and thread pool usage

Key Facts

Category
Java
Items
3
Format Families
sample

Sample Overview

Android Java multithreading examples including thread creation, synchronization with locks, and thread pool usage This sample set belongs to Java and can be used to test related workflows inside Elysia Tools.

💻 Thread Creation java

🟢 simple ⭐⭐⭐

Create and start threads using Thread class, Runnable interface, and ExecutorService

⏱️ 25 min 🏷️ java, android, multithreading, threads
Prerequisites: Basic Java knowledge, Understanding of concurrency
// Android Java Thread Creation Examples
// Using Thread, Runnable, and ExecutorService

import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.*;

// 1. Basic Thread Creation
class BasicThreadCreation {

    // Create thread using Thread class
    public void createBasicThread() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread running: " + Thread.currentThread().getName());
                // Perform background work
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread completed");
            }
        });

        thread.start();
    }

    // Create thread with custom name
    public void createNamedThread(String name) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Named thread: " + Thread.currentThread().getName());
                // Perform work
            }
        }, name);

        thread.start();
    }

    // Create thread using Runnable
    public void createThreadWithRunnable() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable thread: " + Thread.currentThread().getName());
            }
        };

        Thread thread = new Thread(runnable);
        thread.start();
    }

    // Create thread using lambda (Java 8+)
    public void createThreadWithLambda() {
        Thread thread = new Thread(() -> {
            System.out.println("Lambda thread: " + Thread.currentThread().getName());
            performWork();
        });

        thread.start();
    }

    private void performWork() {
        // Simulate work
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Work completed");
    }
}

// 2. Thread with Exception Handling
class ThreadExceptionHandling {

    public void createThreadWithExceptionHandling() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("Thread working...");
                    // Simulate error
                    throw new RuntimeException("Thread error!");
                } catch (Exception e) {
                    System.out.println("Caught exception in thread: " + e.getMessage());
                }
            }
        });

        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("Uncaught exception in " + t.getName() + ": " + e.getMessage());
            }
        });

        thread.start();
    }

    // Thread with priority
    public void createThreadWithPriority() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("High priority thread running");
            }
        });

        thread.setPriority(Thread.MAX_PRIORITY);
        thread.start();
    }

    // Daemon thread
    public void createDaemonThread() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int count = 0;
                while (true) {
                    System.out.println("Daemon thread: " + count);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        break;
                    }
                    count++;
                }
            }
        });

        thread.setDaemon(true);
        thread.start();

        // Main thread exits, daemon thread terminates
    }

    // Thread sleep and join
    public void createThreadWithJoin() {
        final Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread 1 starting");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 1 completed");
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread 2 starting");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 2 completed");
            }
        });

        thread1.start();
        thread2.start();

        // Wait for both threads to complete
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("All threads completed");
    }
}

// 3. Handler and Looper (Android Specific)
class HandlerLooperExample {

    private final Handler handler = new Handler(Looper.getMainLooper());

    // Post runnable to main thread
    public void postToMainThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Background thread: " + Thread.currentThread().getName());

                // Post result to main thread
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("Main thread: " + Thread.currentThread().getName());
                        // Update UI
                    }
                });
            }
        }).start();
    }

    // Post delayed
    public void postDelayed() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                System.out.println("Delayed execution on main thread");
            }
        }, 2000); // 2 seconds delay
    }

    // Post at front of queue
    public void postAtFrontOfQueue() {
        handler.postAtFrontOfQueue(new Runnable() {
            @Override
            public void run() {
                System.out.println("Execute immediately on main thread");
            }
        });
    }

    // Remove callbacks
    public void removeCallbacks() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("This won't execute");
            }
        };

        handler.post(runnable);
        handler.removeCallbacks(runnable);
    }
}

// 4. Thread Communication (Wait and Notify)
class ThreadCommunication {

    private String sharedData = "";

    public void waitNotifyExample() {
        final Object lock = new Object();

        Thread producerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Producer: Producing data...");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    sharedData = "Hello from producer";
                    System.out.println("Producer: Data ready, notifying...");
                    lock.notifyAll();
                }
            }
        });

        Thread consumerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Consumer: Waiting for data...");
                    while (sharedData.isEmpty()) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Consumer: Received: " + sharedData);
                }
            }
        });

        consumerThread.start();
        producerThread.start();
    }
}

// 5. Thread Local Storage
class ThreadLocalStorageExample {

    private ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public void threadLocalDemo() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                threadLocal.set("Value from Thread 1");
                System.out.println("Thread 1: " + threadLocal.get());
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                threadLocal.set("Value from Thread 2");
                System.out.println("Thread 2: " + threadLocal.get());
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Main thread: " + threadLocal.get());
    }
}

// 6. AsyncTask (Deprecated but still useful for understanding)
// Note: AsyncTask is deprecated in API 30, use Coroutines or ExecutorService instead
class ModernAsyncExample {

    private final ExecutorService executor = Executors.newFixedThreadPool(4);
    private final Handler handler = new Handler(Looper.getMainLooper());

    // Modern approach using ExecutorService and Handler
    public void executeAsyncTask() {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                // Background work
                System.out.println("Working in background: " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // Post result to main thread
                final String result = "Task completed";
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("Result on main thread: " + result);
                        // Update UI here
                    }
                });
            }
        });
    }

    // Cancelable task
    public Future<String> submitCancelableTask() {
        Future<String> future = executor.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("Task started");
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(200);
                    System.out.println("Progress: " + (i + 1) * 10 + "%");
                }
                return "Task completed successfully";
            }
        });

        return future;
    }

    public void shutdown() {
        executor.shutdown();
    }
}

// Main demonstration
class ThreadCreationDemo {
    public static void demonstrateThreadCreation() {
        System.out.println("=== Android Java Thread Creation Examples ===\n");

        // 1. Basic thread creation
        System.out.println("--- 1. Basic Thread Creation ---");
        BasicThreadCreation basicThread = new BasicThreadCreation();
        basicThread.createBasicThread();
        basicThread.createNamedThread("MyCustomThread");

        // 2. Lambda thread
        System.out.println("\n--- 2. Lambda Thread ---");
        basicThread.createThreadWithLambda();

        // 3. Exception handling
        System.out.println("\n--- 3. Exception Handling ---");
        ThreadExceptionHandling exceptionHandling = new ThreadExceptionHandling();
        exceptionHandling.createThreadWithJoin();

        // 4. Handler and Looper
        System.out.println("\n--- 4. Handler and Looper ---");
        HandlerLooperExample handlerExample = new HandlerLooperExample();
        handlerExample.postToMainThread();

        // 5. Thread communication
        System.out.println("\n--- 5. Thread Communication ---");
        ThreadCommunication communication = new ThreadCommunication();
        communication.waitNotifyExample();

        // Wait for threads to complete
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("\n=== All Thread Creation Examples Completed ===");
    }
}

💻 Thread Synchronization java

🟡 intermediate ⭐⭐⭐⭐

Synchronize threads using locks, semaphores, and other synchronization mechanisms to protect shared resources

⏱️ 35 min 🏷️ java, android, multithreading, synchronization
Prerequisites: Intermediate Java, Understanding of concurrency
// Android Java Thread Synchronization Examples
// Using locks, semaphores, and synchronization mechanisms

import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;

// 1. Synchronized Block and Method
class SynchronizedBlockExample {
    private int counter = 0;

    // Using synchronized block
    public void incrementCounter() {
        synchronized (this) {
            counter++;
            System.out.println("Counter: " + counter + " (Thread: " + Thread.currentThread().getName() + ")");
        }
    }

    // Synchronized method
    public synchronized void decrementCounter() {
        counter--;
        System.out.println("Counter: " + counter + " (Thread: " + Thread.currentThread().getName() + ")");
    }

    public synchronized int getCounter() {
        return counter;
    }
}

// 2. ReentrantLock
class ReentrantLockExample {
    private final Lock lock = new ReentrantLock();
    private int sharedResource = 0;

    public void performTask() {
        lock.lock();
        try {
            System.out.println("Lock acquired by " + Thread.currentThread().getName());
            // Critical section
            sharedResource++;
            Thread.sleep(100);
            System.out.println("Shared resource: " + sharedResource);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println("Lock released by " + Thread.currentThread().getName());
        }
    }

    public void tryLockExample() {
        try {
            if (lock.tryLock(1, TimeUnit.SECONDS)) {
                try {
                    System.out.println("TryLock succeeded");
                    // Perform work
                } finally {
                    lock.unlock();
                }
            } else {
                System.out.println("Could not acquire lock");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // ReadWriteLock for multiple readers
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private String data = "Initial Data";

    public String readData() {
        readWriteLock.readLock().lock();
        try {
            System.out.println("Reading: " + data);
            return data;
        } finally {
            readWriteLock.readLock().unlock();
        }
    }

    public void writeData(String newValue) {
        readWriteLock.writeLock().lock();
        try {
            System.out.println("Writing: " + newValue);
            data = newValue;
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }
}

// 3. Semaphore
class SemaphoreExample {
    private final Semaphore semaphore = new Semaphore(3); // Allow 3 concurrent accesses

    public void accessResource(int id) {
        try {
            semaphore.acquire();
            System.out.println("Resource " + id + " acquired by " + Thread.currentThread().getName());

            // Simulate work
            Thread.sleep(1000);
            System.out.println("Resource " + id + " released");
        } catch (InterruptedException e) {
            System.out.println("Interrupted: " + e.getMessage());
        } finally {
            semaphore.release();
        }
    }

    public void tryAcquireExample(int id) {
        if (semaphore.tryAcquire()) {
            try {
                System.out.println("Resource " + id + " accessed immediately");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
        } else {
            System.out.println("Resource " + id + " not available");
        }
    }
}

// 4. Atomic Variables
class AtomicVariableExample {
    private final AtomicInteger atomicCounter = new AtomicInteger(0);
    private final AtomicBoolean atomicBoolean = new AtomicBoolean(false);
    private final AtomicReference<String> atomicReference = new AtomicReference<>("Initial");

    public void atomicIncrement() {
        int newValue = atomicCounter.incrementAndGet();
        System.out.println("Atomic counter: " + newValue);
    }

    public void compareAndSet() {
        boolean success = atomicBoolean.compareAndSet(false, true);
        System.out.println("CAS result: " + success + ", Value: " + atomicBoolean.get());
    }

    public void atomicUpdate() {
        atomicReference.updateAndGet(current -> {
            System.out.println("Current: " + current);
            return "Updated";
        });
        System.out.println("Final: " + atomicReference.get());
    }

    public void getAndAdd() {
        int oldValue = atomicCounter.getAndAdd(5);
        System.out.println("Old: " + oldValue + ", New: " + atomicCounter.get());
    }
}

// 5. CountDownLatch
class CountDownLatchExample {
    public void demonstrateLatch() {
        final CountDownLatch latch = new CountDownLatch(3);

        // Create worker threads
        for (int i = 0; i < 3; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("Worker " + index + " starting");
                        Thread.sleep(1000 + (int)(Math.random() * 1000));
                        System.out.println("Worker " + index + " completed");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        latch.countDown();
                    }
                }
            }).start();
        }

        // Main thread waits
        System.out.println("Main thread waiting for workers...");
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("All workers completed!");
    }

    public void awaitWithTimeout() {
        final CountDownLatch latch = new CountDownLatch(5);

        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        latch.countDown();
                    }
                }
            }).start();
        }

        // Wait with timeout
        try {
            if (latch.await(2, TimeUnit.SECONDS)) {
                System.out.println("Completed within timeout");
            } else {
                System.out.println("Timeout - not all completed");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// 6. CyclicBarrier
class CyclicBarrierExample {
    public void demonstrateBarrier() {
        final CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
            @Override
            public void run() {
                System.out.println("\n*** All threads reached barrier ***\n");
            }
        });

        for (int i = 0; i < 3; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("Thread " + index + ": Phase 1");
                        Thread.sleep(500);
                        System.out.println("Thread " + index + ": Waiting at barrier");

                        barrier.await();

                        System.out.println("Thread " + index + ": Phase 2");
                    } catch (Exception e) {
                        System.out.println("Barrier error: " + e.getMessage());
                    }
                }
            }).start();
        }
    }
}

// 7. BlockingQueue (Producer-Consumer)
class BlockingQueueExample {
    private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
    private volatile boolean running = true;

    public void startProducer() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int item = 0;
                while (running) {
                    try {
                        queue.put(item);
                        System.out.println("Produced: " + item + " (Queue size: " + queue.size() + ")");
                        item++;
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
            }
        }).start();
    }

    public void startConsumer() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (running) {
                    try {
                        int item = queue.take();
                        System.out.println("Consumed: " + item);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
            }
        }).start();
    }

    public void stop() {
        running = false;
    }
}

// 8. Volatile Variables
class VolatileExample {
    private volatile boolean flag = false;

    public void startFlagWatcher() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Watcher: Waiting for flag...");
                while (!flag) {
                    // Busy wait (not recommended, use proper synchronization)
                }
                System.out.println("Watcher: Flag is now true!");
            }
        }).start();
    }

    public void setFlag() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("Main: Flag set to true");
    }
}

// 9. Thread-safe Collections
class ThreadSafeCollectionsExample {
    // ConcurrentHashMap
    private final ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();

    public void addToConcurrentMap() {
        for (int i = 0; i < 10; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    concurrentMap.put("key" + index, index);
                    System.out.println("Added key" + index + ": " + index);
                }
            }).start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Map size: " + concurrentMap.size());
    }

    // CopyOnWriteArrayList
    private final CopyOnWriteArrayList<String> concurrentList = new CopyOnWriteArrayList<>();

    public void addToList() {
        for (int i = 0; i < 5; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    concurrentList.add("Item " + index);
                    System.out.println("List size: " + concurrentList.size());
                }
            }).start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("List: " + concurrentList);
    }

    // Concurrent Linked Queue
    private final ConcurrentLinkedQueue<Integer> concurrentQueue = new ConcurrentLinkedQueue<>();

    public void addToQueue() {
        for (int i = 0; i < 5; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    concurrentQueue.offer(index);
                    System.out.println("Queue size: " + concurrentQueue.size());
                }
            }).start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Queue: " + concurrentQueue);
    }
}

// Main demonstration
class ThreadSynchronizationDemo {
    public static void demonstrateThreadSynchronization() {
        System.out.println("=== Android Java Thread Synchronization Examples ===\n");

        // 1. Synchronized block
        System.out.println("--- 1. Synchronized Block ---");
        final SynchronizedBlockExample syncExample = new SynchronizedBlockExample();

        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    syncExample.incrementCounter();
                }
            }).start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 2. ReentrantLock
        System.out.println("\n--- 2. ReentrantLock ---");
        final ReentrantLockExample lockExample = new ReentrantLockExample();

        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    lockExample.performTask();
                }
            }).start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 3. Semaphore
        System.out.println("\n--- 3. Semaphore ---");
        final SemaphoreExample semaphoreExample = new SemaphoreExample();

        for (int i = 0; i < 5; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    semaphoreExample.accessResource(index);
                }
            }).start();
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 4. Atomic variables
        System.out.println("\n--- 4. Atomic Variables ---");
        final AtomicVariableExample atomicExample = new AtomicVariableExample();

        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    atomicExample.atomicIncrement();
                }
            }).start();
        }

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 5. CountDownLatch
        System.out.println("\n--- 5. CountDownLatch ---");
        CountDownLatchExample latchExample = new CountDownLatchExample();
        latchExample.demonstrateLatch();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 6. Thread-safe collections
        System.out.println("\n--- 6. Thread-safe Collections ---");
        ThreadSafeCollectionsExample collectionsExample = new ThreadSafeCollectionsExample();
        collectionsExample.addToConcurrentMap();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("\n=== All Thread Synchronization Examples Completed ===");
    }
}

💻 Thread Pool Usage java

🟡 intermediate ⭐⭐⭐⭐

Use thread pools efficiently with ExecutorService, custom thread pool configurations, and Future objects

⏱️ 40 min 🏷️ java, android, multithreading, thread pool
Prerequisites: Intermediate Java, Understanding of thread pools
// Android Java Thread Pool Examples
// Using ExecutorService, Custom Thread Pools, and Future

import java.util.concurrent.*;
import java.util.List;
import java.util.ArrayList;

// 1. ExecutorService Thread Pools
class ExecutorServicePools {

    // Fixed thread pool
    public void fixedThreadPoolExample() {
        ExecutorService executor = Executors.newFixedThreadPool(4);

        System.out.println("--- Fixed Thread Pool (4 threads) ---");

        long startTime = System.currentTimeMillis();

        List<Future<Void>> futures = new ArrayList<>();
        for (int taskId = 1; taskId <= 8; taskId++) {
            final int finalTaskId = taskId;
            Future<Void> future = executor.submit(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    System.out.println("Task " + finalTaskId + " starting on " + Thread.currentThread().getName());
                    Thread.sleep(1000);
                    System.out.println("Task " + finalTaskId + " completed");
                    return null;
                }
            });
            futures.add(future);
        }

        // Wait for all tasks to complete
        for (Future<Void> future : futures) {
            try {
                future.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        long endTime = System.currentTimeMillis();
        System.out.println("Total time: " + (endTime - startTime) + "ms");

        executor.shutdown();
    }

    // Cached thread pool
    public void cachedThreadPoolExample() {
        ExecutorService executor = Executors.newCachedThreadPool();

        System.out.println("\n--- Cached Thread Pool ---");

        List<Future<Integer>> futures = new ArrayList<>();
        for (int taskId = 1; taskId <= 10; taskId++) {
            final int finalTaskId = taskId;
            Future<Integer> future = executor.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    System.out.println("Task " + finalTaskId + " on " + Thread.currentThread().getName());
                    Thread.sleep(100 + (int)(Math.random() * 400));
                    return finalTaskId * 2;
                }
            });
            futures.add(future);
        }

        for (Future<Integer> future : futures) {
            try {
                Integer result = future.get();
                System.out.println("Result: " + result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        executor.shutdown();
    }

    // Single thread executor
    public void singleThreadExecutorExample() {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        System.out.println("\n--- Single Thread Executor ---");

        for (int taskId = 1; taskId <= 5; taskId++) {
            final int finalTaskId = taskId;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Task " + finalTaskId + " on " + Thread.currentThread().getName());
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        executor.shutdown();
        try {
            executor.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // Scheduled executor
    public void scheduledExecutorExample() {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

        System.out.println("\n--- Scheduled Executor ---");

        // Schedule one-time task
        executor.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("Delayed task executed");
            }
        }, 2, TimeUnit.SECONDS);

        // Schedule at fixed rate
        final ScheduledFuture<?> future = executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("Periodic task at " + System.currentTimeMillis());
            }
        }, 0, 1, TimeUnit.SECONDS);

        // Run for 5 seconds then shutdown
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        future.cancel(true);
        executor.shutdown();
    }
}

// 2. Custom Thread Pool
class CustomThreadPoolExample {

    public void customThreadPoolExample() {
        // Create custom thread pool
        ThreadFactory threadFactory = new ThreadFactory() {
            private int count = 0;

            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("CustomPool-" + System.currentTimeMillis() + "-" + count++);
                thread.setDaemon(false);
                thread.setPriority(Thread.NORM_PRIORITY);
                return thread;
            }
        };

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, // Core pool size
            5, // Maximum pool size
            60L, // Keep-alive time
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(10), // Work queue
            threadFactory,
            new ThreadPoolExecutor.CallerRunsPolicy() // Rejection policy
        );

        System.out.println("\n--- Custom Thread Pool ---");

        // Submit tasks
        for (int i = 1; i <= 10; i++) {
            final int taskId = i;
            try {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("Task " + taskId + " on " + Thread.currentThread().getName());
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
            } catch (RejectedExecutionException e) {
                System.out.println("Task " + i + " rejected");
            }
        }

        executor.shutdown();
        try {
            executor.awaitTermination(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// 3. ExecutorService with Future
class FutureExample {

    public void submitWithFuture() {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        System.out.println("\n--- ExecutorService with Future ---");

        // Submit callable tasks
        List<Future<Integer>> futures = new ArrayList<>();
        for (int taskId = 1; taskId <= 5; taskId++) {
            final int finalTaskId = taskId;
            Future<Integer> future = executor.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    System.out.println("Task " + finalTaskId + " starting");
                    Thread.sleep(500 + (int)(Math.random() * 1000));
                    System.out.println("Task " + finalTaskId + " completed");
                    return finalTaskId * 10;
                }
            });
            futures.add(future);
        }

        // Process results as they complete
        for (Future<Integer> future : futures) {
            try {
                Integer result = future.get();
                System.out.println("Future result: " + result);
            } catch (Exception e) {
                System.out.println("Future error: " + e.getMessage());
            }
        }

        executor.shutdown();
    }

    public void invokeAllExample() {
        ExecutorService executor = Executors.newFixedThreadPool(4);

        List<Callable<Integer>> tasks = new ArrayList<>();
        for (int taskId = 1; taskId <= 10; taskId++) {
            final int finalTaskId = taskId;
            tasks.add(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    Thread.sleep(1000);
                    return finalTaskId;
                }
            });
        }

        long startTime = System.currentTimeMillis();

        try {
            List<Future<Integer>> futures = executor.invokeAll(tasks);

            for (Future<Integer> future : futures) {
                System.out.println("Completed: " + future.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();
        System.out.println("InvokeAll time: " + (endTime - startTime) + "ms");

        executor.shutdown();
    }

    public void invokeAnyExample() {
        ExecutorService executor = Executors.newFixedThreadPool(4);

        List<Callable<Integer>> tasks = new ArrayList<>();
        for (int taskId = 1; taskId <= 5; taskId++) {
            final int finalTaskId = taskId;
            tasks.add(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int sleepTime = (int)(Math.random() * 3000) + 1000;
                    System.out.println("Task " + finalTaskId + " will take " + sleepTime + "ms");
                    Thread.sleep(sleepTime);
                    return finalTaskId;
                }
            });
        }

        try {
            Integer result = executor.invokeAny(tasks);
            System.out.println("First completed task: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }

        executor.shutdown();
    }
}

// 4. Completion Service
class CompletionServiceExample {

    public void completionServiceDemo() {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        CompletionService<Integer> completionService = new ExecutorCompletionService<>(executor);

        System.out.println("\n--- Completion Service ---");

        // Submit tasks
        for (int taskId = 1; taskId <= 5; taskId++) {
            final int finalTaskId = taskId;
            completionService.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int sleepTime = 1000 + (int)(Math.random() * 2000);
                    System.out.println("Task " + finalTaskId + " will take " + sleepTime + "ms");
                    Thread.sleep(sleepTime);
                    return finalTaskId;
                }
            });
        }

        // Process as they complete
        for (int i = 0; i < 5; i++) {
            try {
                Future<Integer> future = completionService.take();
                Integer result = future.get();
                System.out.println("Completed task: " + result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        executor.shutdown();
    }
}

// 5. ForkJoin Pool (Parallel processing)
class ForkJoinPoolExample {

    public void parallelSum() {
        ForkJoinPool pool = new ForkJoinPool();

        System.out.println("\n--- ForkJoin Pool ---");

        RecursiveSumTask task = new RecursiveSumTask(1, 1000000);
        Integer result = pool.invoke(task);

        System.out.println("Parallel sum result: " + result);
        pool.shutdown();
    }

    public static class RecursiveSumTask extends RecursiveTask<Integer> {
        private final int start;
        private final int end;

        public RecursiveSumTask(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            if (end - start <= 10000) {
                // Compute directly
                int sum = 0;
                for (int i = start; i <= end; i++) {
                    sum += i;
                }
                return sum;
            } else {
                // Split task
                int mid = (start + end) / 2;
                RecursiveSumTask leftTask = new RecursiveSumTask(start, mid);
                RecursiveSumTask rightTask = new RecursiveSumTask(mid + 1, end);

                leftTask.fork();
                Integer rightResult = rightTask.compute();
                Integer leftResult = leftTask.join();

                return leftResult + rightResult;
            }
        }
    }
}

// 6. Async Tasks with Callback
class AsyncWithCallback {

    public interface AsyncCallback<T> {
        void onSuccess(T result);
        void onFailure(Exception e);
    }

    public void executeAsyncTask(final AsyncCallback<String> callback) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        executor.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                // Simulate work
                Thread.sleep(1000);
                return "Task completed successfully";
            }
        }).addCallback(new AsyncCallback<String>() {
            @Override
            public void onSuccess(String result) {
                callback.onSuccess(result);
            }

            @Override
            public void onFailure(Exception e) {
                callback.onFailure(e);
            }
        });

        executor.shutdown();
    }

    // Helper method to add callback to Future
    private <T> Future<T> addCallback(final Future<T> future, final AsyncCallback<T> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    T result = future.get();
                    callback.onSuccess(result);
                } catch (Exception e) {
                    callback.onFailure(e);
                }
            }
        }).start();

        return future;
    }
}

// 7. Thread Pool Monitoring
class ThreadPoolMonitoring {

    public void monitorThreadPool() {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, 4, 60, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(10)
        );

        System.out.println("\n--- Thread Pool Monitoring ---");

        // Start monitoring thread
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!executor.isTerminated()) {
                    System.out.println("Active: " + executor.getActiveCount() +
                                     ", Pool: " + executor.getPoolSize() +
                                     ", Queue: " + executor.getQueue().size() +
                                     ", Completed: " + executor.getCompletedTaskCount());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
            }
        }).start();

        // Submit some tasks
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                        System.out.println("Task " + taskId + " completed");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        executor.shutdown();
        try {
            executor.awaitTermination(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// Main demonstration
class ThreadPoolDemo {
    public static void demonstrateThreadPoolUsage() {
        System.out.println("=== Android Java Thread Pool Examples ===\n");

        // 1. ExecutorService pools
        ExecutorServicePools executorPools = new ExecutorServicePools();
        executorPools.fixedThreadPoolExample();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        executorPools.cachedThreadPoolExample();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        executorPools.singleThreadExecutorExample();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        executorPools.scheduledExecutorExample();

        // 2. Custom thread pool
        CustomThreadPoolExample customPool = new CustomThreadPoolExample();
        customPool.customThreadPoolExample();

        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 3. Future example
        System.out.println("\n--- Future Examples ---");
        FutureExample futureExample = new FutureExample();
        futureExample.submitWithFuture();

        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        futureExample.invokeAnyExample();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 4. Completion service
        CompletionServiceExample completionExample = new CompletionServiceExample();
        completionExample.completionServiceDemo();

        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 5. ForkJoin pool
        ForkJoinPoolExample forkJoinExample = new ForkJoinPoolExample();
        forkJoinExample.parallelSum();

        // 6. Thread pool monitoring
        ThreadPoolMonitoring monitoring = new ThreadPoolMonitoring();
        monitoring.monitorThreadPool();

        try {
            Thread.sleep(12000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("\n=== All Thread Pool Examples Completed ===");
    }
}