Threads & Runnable

Java-র মূল concurrency primitive — Thread ও Runnable

Read: ~30 min Advanced 5 practice problems Live code runner

1. What Is a Thread?

A thread is an independent path of execution inside one process. Your Java program always has at least one — the main thread — that starts when main is called. You can spawn more threads to do work in parallel: downloading files, serving HTTP requests, running background tasks. When they all finish, the JVM exits.

thread হলো একই process-এর ভেতরে একটি স্বাধীন execution path। প্রতিটি Java প্রোগ্রামে অন্তত একটি thread থাকে — main thread, যা main call হলে শুরু হয়। সমান্তরালে কাজ করতে আরো thread বানানো যায় — download, HTTP, background task। সব thread শেষ হলে JVM বন্ধ হয়।
Why bother? A modern CPU has 4–32 cores. A single-threaded program uses one. Concurrency lets your program use the whole machine — and stay responsive while waiting for I/O.

2. Two Ways to Start a Thread

There are two basic ways: extend Thread, or pass a Runnable (a lambda) to a new Thread. The second is always preferred — composition over inheritance.

দুটি মূল উপায় — Thread extend করা, অথবা একটি Runnable (lambda) নতুন Thread-এ পাস করা। দ্বিতীয়টাই সবসময় ভালো — inheritance-এর বদলে composition।
Main.java
class Main {
    public static void main(String[] args) throws Exception {
        Runnable task = () -> {
            for (int i = 1; i <= 3; i++) {
                System.out.println(Thread.currentThread().getName()
                    + " - tick " + i);
            }
        };

        Thread t1 = new Thread(task, "worker-1");
        Thread t2 = new Thread(task, "worker-2");
        t1.start();
        t2.start();

        // wait for them to finish before main exits
        t1.join();
        t2.join();
        System.out.println("main done");
    }
}
Output is interleaved and non-deterministic. The OS scheduler chooses which thread runs when. Do not expect a particular order.

3. start() vs run() — The Classic Bug

thread.start() spawns a new OS thread and runs your code on it. thread.run() calls the method directly on the current thread — no concurrency at all. It is one of the most common beginner bugs in Java.

thread.start() নতুন OS thread তৈরি করে সেখানে আপনার কোড চালায়। thread.run() current thread-এই method call করে — concurrency থাকে না। এটা Java-র একটি classic beginner bug।
start() spawns a new thread · run() does NOT t.start() main thread worker thread t.run() ← bug main thread (no second thread) Figure 37.1 — start আলাদা thread বানায়; run বানায় না।

4. join() — Waiting for a Thread to Finish

If your main thread finishes before its workers, the JVM may shut down half-way through. join() blocks until the target thread completes. For a set of workers, loop and join each one.

main শেষ হয়ে গেলেও JVM সাথে সাথে বন্ধ হয় না যতক্ষণ user thread চলছে — কিন্তু সঠিক ordering-এ output পেতে join() ব্যবহার করুন। এটা target thread শেষ না হওয়া পর্যন্ত অপেক্ষা করে।
Main.java
class Main {
    public static void main(String[] args) throws Exception {
        Thread t = new Thread(() -> {
            try { Thread.sleep(50); } catch (InterruptedException e) {}
            System.out.println("worker finished");
        });

        t.start();
        System.out.println("main waiting...");
        t.join();  // block until worker is done
        System.out.println("main after join");
    }
}

5. Interrupting a Thread

You cannot kill a thread in Java — you can only politely ask it to stop via interrupt(). A well-behaved thread checks Thread.currentThread().isInterrupted() periodically and also catches InterruptedException from sleep / wait. Never swallow the exception silently.

Java-তে thread জোর করে kill করা যায় না — শুধু interrupt() দিয়ে politely অনুরোধ। ভালো thread নিয়মিত isInterrupted() check করে এবং sleep/wait-এর InterruptedException handle করে। exception কখনো silently swallow করবেন না।
Main.java
class Main {
    public static void main(String[] args) throws Exception {
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("...working");
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    System.out.println("got interrupt — exiting");
                    Thread.currentThread().interrupt();  // preserve flag
                    return;
                }
            }
        });
        t.start();
        Thread.sleep(100);
        t.interrupt();
        t.join();
        System.out.println("done");
    }
}

6. Daemon Threads

A daemon thread runs in the background and does not block JVM exit. Garbage collection, JIT compilation, and timer threads are typically daemons. Mark a thread daemon before starting it with t.setDaemon(true).

daemon thread background-এ চলে এবং JVM exit-কে block করে না। GC, JIT, timer thread — এগুলো সাধারণত daemon। start করার আগে t.setDaemon(true) দিয়ে mark করুন।
StateMeaningবাংলায়
NEWcreated but not startedতৈরি হয়েছে, শুরু হয়নি
RUNNABLErunning or ready to runচলছে বা চলতে প্রস্তুত
BLOCKEDwaiting for a monitor locklock-এর জন্য অপেক্ষা
WAITINGwaiting indefinitely (join, wait)অনির্দিষ্ট অপেক্ষা
TIMED_WAITINGwaiting with timeout (sleep, wait(ms))timeout-সহ অপেক্ষা
TERMINATEDfinishedশেষ হয়ে গেছে

7. Vocabulary

TermMeaningবাংলায়
ThreadIndependent path of execution.স্বাধীন execution path।
RunnableFunctional interface — a task with no return value.functional interface — return-less task।
start()Launches a new OS thread; invokes run() there.নতুন OS thread শুরু করে।
join()Blocks until target thread finishes.target thread শেষ হওয়া পর্যন্ত অপেক্ষা।
interrupt()Polite request to stop.থামার polite অনুরোধ।
DaemonBackground thread that does not block JVM exit.background thread — JVM exit block করে না।

8. Practice Problems

  1. Start two threads that each print their name three times; wait for both to finish.
    দুটি thread চালান যারা নিজ নিজ নাম তিনবার print করবে; দুটিই শেষ হওয়া পর্যন্ত অপেক্ষা করুন।
    Show Answer (উত্তর দেখুন)
    Main.java
    class Main {
        public static void main(String[] args) throws Exception {
            Runnable r = () -> {
                for (int i = 0; i < 3; i++)
                    System.out.println(Thread.currentThread().getName());
            };
            Thread a = new Thread(r, "A");
            Thread b = new Thread(r, "B");
            a.start(); b.start();
            a.join();  b.join();
            System.out.println("main done");
        }
    }
  2. Explain in 2 sentences the difference between t.start() and t.run().
    দুই বাক্যে পার্থক্য ব্যাখ্যা করুন — t.start() বনাম t.run()।
    Show Answer (উত্তর দেখুন)

    Answer: start() asks the JVM to create a brand-new OS thread and invoke run() on that new thread, so the caller returns immediately. run() is just a regular method call on the current thread — no new thread exists and the caller waits for it to return, so you get zero parallelism.

    start() JVM-কে বলে নতুন OS thread বানাতে এবং সেখানে run() চালাতে — তাই caller সাথে সাথে return করে। run() current thread-এই সাধারণ method call — নতুন thread তৈরি হয় না, caller অপেক্ষা করে।

  3. Launch a worker that increments a counter 1000 times and prints the final value.
    একটি worker চালান যা counter ১০০০ বার বাড়িয়ে শেষ মান print করবে।
    Show Answer (উত্তর দেখুন)
    Main.java
    class Main {
        static int counter = 0;
        public static void main(String[] args) throws Exception {
            Thread t = new Thread(() -> {
                for (int i = 0; i < 1000; i++) counter++;
            });
            t.start();
            t.join();
            System.out.println("counter = " + counter);
        }
    }
  4. Interrupt a sleeping thread and print the exception class.
    একটি ঘুমন্ত thread-কে interrupt করে exception-এর class print করুন।
    Show Answer (উত্তর দেখুন)
    Main.java
    class Main {
        public static void main(String[] args) throws Exception {
            Thread t = new Thread(() -> {
                try {
                    Thread.sleep(10000);
                } catch (Exception e) {
                    System.out.println("caught " + e.getClass().getSimpleName());
                }
            });
            t.start();
            Thread.sleep(30);
            t.interrupt();
            t.join();
        }
    }
  5. In 3 sentences, explain why you cannot simply "kill" a thread in modern Java.
    তিন বাক্যে বলুন — আধুনিক Java-তে thread কেন "kill" করা যায় না।
    Show Answer (উত্তর দেখুন)

    Answer: The old Thread.stop() method existed but was deprecated because abruptly killing a thread left shared data in a broken, half-updated state with locks held mid-transaction. Cooperative cancellation via interrupt() gives the thread a chance to finish a unit of work, release locks, and clean up. It is slower to stop a thread but prevents the far worse problem of corrupted program state.

    পুরনো Thread.stop() থাকলেও deprecated — হঠাৎ kill করলে shared data অর্ধ-আপডেট অবস্থায়, lock ধরা অবস্থায় থাকতে পারে। interrupt()-এর cooperative cancellation thread-কে কাজ শেষ করতে, lock ছাড়তে, cleanup করতে সুযোগ দেয়। থামতে সামান্য সময় বেশি লাগে, কিন্তু corrupted state এড়ায়।

Summary — Module 37

A thread is an independent execution path within a process. Create one by passing a Runnable lambda to new Thread(...) and calling start() — never run(). Use join() to wait for completion, interrupt() to politely cancel, and setDaemon(true) for background work. Threads give you parallelism; the next modules show how to share data among them safely.

Thread = process-এর ভেতরের স্বাধীন execution path। Runnable lambda পাস করে new Thread(...), তারপর start() — কখনো run() নয়। join() অপেক্ষা, interrupt() বাতিল, setDaemon(true) background। পরবর্তী module-এ thread-এর মধ্যে নিরাপদে data share করা।

Next Module → Synchronization — synchronized, volatile, atomic।