JavaScript में कंकरेंसी और मल्टीथ्रेडिंग: कोड को तेज़ी से कैसे चलाएँ
JavaScript ऐतिहासिक रूप से एक सिंगल-थ्रेडेड भाषा रही है, लेकिन इसका मतलब यह नहीं है कि यह एक साथ कई कार्यों को संसाधित नहीं कर सकती। आधुनिक Node.js और ब्राउज़रों में कंकरेंसी और मल्टीथ्रेडिंग के साथ काम करने के लिए शक्तिशाली तंत्र मौजूद हैं। उच्च-प्रदर्शन वाले सर्वर और क्लाइंट एप्लिकेशन बनाने के लिए इन अवधारणाओं को समझना महत्वपूर्ण है।
इस लेख में, हम समझेंगे कि कंकरेंसी पैरेललिज़्म से कैसे भिन्न है, Event Loop कैसे काम करता है, Worker Threads और Web Workers का उपयोग कब करना चाहिए, और Node.js पर व्यावहारिक उदाहरण देखेंगे।
1. Event Loop और नॉन-ब्लॉकिंग I/O
JavaScript में कंकरेंसी का आधार Event Loop (इवेंट लूप) है। यह एक तंत्र है जो मुख्य थ्रेड को ब्लॉक किए बिना एसिंक्रोनस ऑपरेशन (जैसे फ़ाइल पढ़ना, डेटाबेस क्वेरी) को निष्पादित करने की अनुमति देता है।
एक कतार की कल्पना करें: Event Loop कतार (call stack) से एक कार्य लेता है, उसे निष्पादित करता है, और यदि उसे कोई एसिंक्रोनस ऑपरेशन (जैसे setTimeout या fetch) मिलता है, तो उसे Web API (ब्राउज़र में) या libuv (Node.js में) को भेज देता है। ऑपरेशन पूरा होने के बाद, इसका कॉलबैक टास्क कतार (task queue) में आ जाता है। Event Loop लगातार जाँचता है कि स्टैक खाली है या नहीं, और यदि यह खाली है, तो कतार से अगला कार्य ले लेता है।
एसिंक्रोनस कोड का उदाहरण:
const fs = require('fs');
console.log('शुरू');
fs.readFile('example.txt', 'utf8', (err, data) => { if (err) throw err; console.log('फ़ाइल पढ़ी गई:', data);});
console.log('अंत');
// आउटपुट:// शुरू// अंत// फ़ाइल पढ़ी गई: ...ध्यान दें: console.log('अंत') फ़ाइल पढ़ने से पहले निष्पादित होता है। यही नॉन-ब्लॉकिंग I/O है — मुख्य थ्रेड ऑपरेशन के पूरा होने की प्रतीक्षा नहीं करता, बल्कि निष्पादन जारी रखता है।
2. Web Workers और Worker Threads: वास्तविक मल्टीथ्रेडिंग
हालाँकि Event Loop I/O ऑपरेशन के लिए बढ़िया काम करता है, लेकिन यह "भारी" गणनाओं (इमेज प्रोसेसिंग, क्रिप्टोग्राफी, जटिल सॉर्टिंग) को निष्पादित करने में मदद नहीं करता। यदि ऐसे कोड को मुख्य थ्रेड में चलाया जाए, तो गणना पूरी होने तक पूरा इंटरफ़ेस (या सर्वर) "फ़्रीज़" हो जाएगा।
इस समस्या को हल करने के लिए Web Workers (ब्राउज़र में) और Worker Threads (Node.js में) मौजूद हैं। ये ऑपरेटिंग सिस्टम के अलग-अलग थ्रेड्स में JavaScript कोड चलाने की अनुमति देते हैं।
Node.js में Worker Threads का उदाहरण
एक फ़ाइल worker.js बनाएँ:
const { parentPort } = require('worker_threads');
// भारी कार्य: संख्याओं के योग की गणनाlet sum = 0;for (let i = 0; i < 1e9; i++) { sum += i;}
// परिणाम मुख्य थ्रेड को वापस भेजेंparentPort.postMessage(sum);मुख्य फ़ाइल main.js:
const { Worker } = require('worker_threads');
console.log('मुख्य थ्रेड: वर्कर शुरू कर रहा है');
const worker = new Worker('./worker.js');
worker.on('message', (result) => { console.log('वर्कर से परिणाम:', result);});
worker.on('error', (err) => { console.error('वर्कर में त्रुटि:', err);});
worker.on('exit', (code) => { if (code !== 0) { console.error(`वर्कर कोड ${code} के साथ समाप्त हुआ`); }});
console.log('मुख्य थ्रेड: काम जारी है...');
// आउटपुट:// मुख्य थ्रेड: वर्कर शुरू कर रहा है// मुख्य थ्रेड: काम जारी है...// वर्कर से परिणाम: 499999999500000000जैसा कि आप देख सकते हैं, मुख्य थ्रेड ब्लॉक नहीं होता है, और वर्कर पृष्ठभूमि में गणना करता है। यही वास्तविक मल्टीथ्रेडिंग है।
3. Async/Await और Promise: कंकरेंसी का प्रबंधन
आधुनिक JavaScript एसिंक्रोनस कोड के साथ काम करने के लिए सुरुचिपूर्ण तरीके प्रदान करता है — async/await और Promise। ये नए थ्रेड नहीं बनाते, लेकिन
```