जब आपका कोड हकलाने लगे: Java में कतारों और पृष्ठभूमि कार्यों का परिचय
\n\nएक स्थिति की कल्पना करें: आप Java पर एक वेब सर्वर चला रहे हैं। उपयोगकर्ता से एक अनुरोध आता है — एक ईमेल भेजना, PDF रिपोर्ट जनरेट करना और आँकड़े अपडेट करना आवश्यक है। यदि सब कुछ सिंक्रोनस रूप से किया जाए, तो उपयोगकर्ता को 30 सेकंड इंतजार करना होगा। उसकी कॉफी ठंडी हो जाएगी, और वह प्रतिस्पर्धियों के पास चला जाएगा। परिचित लगता है?
\n\nJava पृष्ठभूमि कार्यों की दुनिया में, इसे सुरुचिपूर्ण ढंग से हल किया जाता है: हम कार्य को एक कतार में डालते हैं और उपयोगकर्ता को '200 OK' लौटाते हैं। फिर, पृष्ठभूमि में, हमारा वर्कर शांति से ईमेल, PDF और आँकड़ों को संसाधित करता है। कोई अव्यवस्था नहीं, केवल व्यवस्था।
\n\nआज हम देखेंगे कि Java में कार्य कतारों को कैसे लागू किया जाए — सबसे सरल सिंगल-थ्रेडेड विकल्प से लेकर RabbitMQ और Kafka के साथ औद्योगिक समाधानों तक। आप सीखेंगे कि आग बुझाना कैसे बंद करें और विश्वसनीय सिस्टम डिज़ाइन करना कैसे शुरू करें।
\n\nकतारों की आवश्यकता क्यों है? तीन कारण जो आपको हैरान कर देंगे
\n\n- \n
- एसिंक्रोनसी — उपयोगकर्ता इंतजार नहीं करता। सर्वर प्रतिक्रिया गति 30 सेकंड से घटकर 5 मिलीसेकंड हो जाती है। \n
- लोड संतुलन — पीक अनुरोध सर्वर को क्रैश नहीं करते। कार्य कतार में संग्रहीत होते हैं और संसाधनों के खाली होने पर संसाधित होते हैं। \n
- दोष सहनशीलता — यदि एक वर्कर डाउन हो जाता है, तो कार्य कतार में रहता है। दूसरा वर्कर इसे उठा लेगा। डेटा नष्ट नहीं होता। \n
Java में इसके लिए अंतर्निहित उपकरण (ExecutorService, BlockingQueue) और बाहरी ब्रोकर (RabbitMQ, Kafka) हैं। चुनाव पैमाने पर निर्भर करता है। छोटे से शुरू करते हैं।
Java में सरल कतार: ExecutorService और BlockingQueue
\n\nयदि आपको वितरित सिस्टम की आवश्यकता नहीं है, बल्कि केवल भारी काम को पृष्ठभूमि में ले जाना चाहते हैं — तो ThreadPoolExecutor का उपयोग करें। यह एक अंतर्निहित थ्रेड पूल है जो कतार से कार्य लेता है।
उदाहरण: ऑर्डर प्रसंस्करण के लिए थ्रेड पूल
\n\nimport java.util.concurrent.*;\n\npublic class OrderProcessor {\n private final ExecutorService executor;\n\n public OrderProcessor(int threadCount) {\n // निश्चित संख्या में थ्रेड के साथ पूल बनाएँ\n this.executor = Executors.newFixedThreadPool(threadCount);\n }\n\n public void processOrder(Order order) {\n executor.submit(() -> {\n // भारी काम: रसीद जनरेट करना, ईमेल भेजना, स्टॉक अपडेट करना\n System.out.println("ऑर्डर प्रसंस्करण: " + order.getId());\n try {\n Thread.sleep(2000); // काम का अनुकरण\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n System.out.println("ऑर्डर " + order.getId() + " संसाधित");\n });\n }\n\n public void shutdown() {\n executor.shutdown();\n }\n\n public static void main(String[] args) {\n OrderProcessor processor = new OrderProcessor(4);\n for (int i = 0; i < 10; i++) {\n processor.processOrder(new Order(i));\n }\n processor.shutdown();\n }\n}\n\nclass Order {\n private final int id;\n public Order(int id) { this.id = id; }\n public int getId() { return id; }\n}\n\nयहाँ क्या हो रहा है? हमने 4 थ्रेड का एक पूल बनाया। 10 ऑर्डर समानांतर रूप से 4-4 के समूहों में संसाधित होंगे। Java में कार्य कतार ThreadPoolExecutor के अंदर प्रबंधित होती है — डिफ़ॉल्ट रूप से यह LinkedBlockingQueue है। जब सभी थ्रेड व्यस्त होते हैं, कार्य अपनी बारी का इंतजार करते हैं।
उन्नत कॉन्फ़िगरेशन: प्राथमिकताएँ और दोष सहनशीलता
\n\nक्या होगा यदि कार्य तत्काल हों? PriorityBlockingQueue का उपयोग करें:
BlockingQueue<Runnable> priorityQueue = new PriorityBlockingQueue<>(\n 10,\n Comparator.comparingInt(task -> ((PriorityTask) task).getPriority())\n);\n\nThreadPoolExecutor executor = new ThreadPoolExecutor(\n 2, 4, 60, TimeUnit.SECONDS, priorityQueue\n);\n\nअब उच्च प्राथमिकता वाले कार्य