Multithreading
Thread program का एक independent flow है। Normally Java एक thread (main) में चलता है।
Thread class extend करके या Runnable implement करके नए threads बना सकते हो, जो parallel काम करते हैं।
class MyThread extends Thread {
public void run() { System.out.println("Running..."); }
}
new MyThread().start();- Thread = independent execution path
- Parallel काम एक साथ होता है
- synchronized से data safe रहता है
Thread class extend करो और run() override करो — simple है लेकिन यह "extends" slot use कर लेता है (Java single inheritance है, इसलिए तुम्हारी class अब कुछ और extend नहीं कर सकती)।
या Runnable interface implement करो और उसे Thread को pass करो — यह better practice है क्योंकि class दूसरी भी extend कर सकती है, और behavior (Runnable — "क्या करना है") thread (Thread — "कैसे चलाना है") से अलग रहता है। Modern Java में Runnable approach ही ज़्यादा recommend होती है।
| extends Thread | implements Runnable | |
|---|---|---|
| दूसरी class extend कर सकते हो? | नहीं | हाँ |
| Recommended? | कम | ज़्यादा (best practice) |
| ExecutorService के साथ use | मुश्किल | आसान |
class MyTask implements Runnable {
public void run() { System.out.println("Running!"); }
}
Thread t = new Thread(new MyTask());
t.start();हर thread की priority होती है (1 से 10, default 5, setPriority() से change कर सकते हो) — JVM को एक "hint" देता है किस thread को ज़्यादा CPU time मिलना चाहिए (guarantee नहीं है, OS-dependent, कई OS इस hint को ignore भी कर सकते हैं)।
Daemon thread background service threads होते हैं (जैसे Garbage Collector खुद एक daemon thread है) — जब सारे non-daemon (normal) threads खत्म हो जाते हैं, JVM daemon threads की परवाह किए बिना exit हो जाता है। setDaemon(true) से किसी thread को daemon बनाया जा सकता है (start() से पहले call करना ज़रूरी है)।
Thread.sleep(ms) current thread को कुछ देर के लिए "pause" कर देता है — कोई दूसरा thread का wait नहीं कर रहा, बस अपना time pass कर रहा है (यह static method है, current thread पर ही असर करता है)।
t.join() एक thread को दूसरे thread (t) के *खत्म होने तक* wait करवाता है — जैसे main thread चाहता हो कि worker thread पहले अपना काम पूरा करे, तब ही आगे बढ़े। यह तब useful है जब result एक thread से दूसरे thread को चाहिए।
Thread worker = new Thread(() -> doWork());
worker.start();
worker.join(); // main thread yaha wait karega worker khatam hone tak
System.out.println("Worker done, ab aage badho");जब multiple threads एक shared variable को simultaneously change करने की कोशिश करते हैं बिना proper synchronization के, result unpredictable हो जाता है — इसको "race condition" कहते हैं।
जैसे दो threads एक counter को ++ कर रहे हों: count++ actually 3 steps हैं (read current value, add 1, write back) — अगर दोनों threads एक साथ "read" कर लें पुरानी value, दोनों अपना-अपना increment लिखेंगे, लेकिन एक update "lost" हो जाएगा (final value expected से कम आएगी)।
// DANGEROUS without synchronization:
class Counter {
int count = 0;
void increment() { count++; } // NOT atomic! race condition risk
}