प्रॉम्प्ट और उपयोग का मामला (Use Case)
एक Java सर्विस को हर मेथड में पैरामीटर जोड़े बिना या रीयूज़ किए गए पूल के माध्यम से स्टेट लीक किए बिना, डीप कॉलबैक्स और वर्चुअल थ्रेड्स में ट्रेस आईडी, टेनेंट, या सिक्योरिटी प्रिंसिपल पास करना होगा। Java 25 ScopedValue लेक्सिकल स्कोप, बाइंडिंग और रीबाइंडिंग, Carrier, वर्चुअल थ्रेड्स, और स्ट्रक्चर्ड कॉनकरेंसी को समझाएं, फिर ThreadLocal से माइग्रेट करने की सीमा निर्धारित करें।
इंटरव्यूअर क्या टेस्ट कर रहा है
- इम्प्लिसिट कॉन्टेक्स्ट की विज़िबल रेंज और लाइफटाइम को समझाना।
- यह समझना कि
ScopedValueबाइंडिंग केवलrun,call, याwhereस्कोप के अंदर ही पढ़ने योग्य है। - इम्यूटेबल स्नैपशॉट प्रोपेगेशन और म्यूटेबल थ्रेड-लोकल स्टेट के बीच अंतर करना।
- नेस्टेड बाइंडिंग्स, चाइल्ड टास्क, एक्सेप्शन्स, और कैंसिलेशन को संभालना।
- सिक्योरिटी-प्रिंसिपल, म्यूटेबल-ऑब्जेक्ट, और पूल-माइग्रेशन जोखिमों को पहचानना।
पहले स्पष्ट करने योग्य प्रश्न
- क्या कॉन्टेक्स्ट एक रिक्वेस्ट-स्कोप वाली रीड-ओनली वैल्यू है या म्यूटेबल स्टेट है जिसे थ्रेड्स के बीच वापस लिखा जाना चाहिए?
- क्या टास्क वर्चुअल थ्रेड्स, स्ट्रक्चर्ड कॉनकरेंसी, या पारंपरिक पूल का उपयोग कर रहे हैं?
- क्या चाइल्ड टास्क को कॉन्टेक्स्ट इनहेरिट करना चाहिए, और क्या वे किसी की (key) को ओवरराइड कर सकते हैं?
- कौन से JDK वर्ज़न समर्थित हैं, और क्या माइग्रेशन को चरणों में पूरा किया जा सकता है?
तीस सेकंड का उत्तर
रिक्वेस्ट कॉन्टेक्स्ट को एक इम्यूटेबल वैल्यू के रूप में मॉडल करें और ScopedValue.where(key, value).run या call के साथ एक लेक्सिकल स्कोप बनाएं। डीप कोड की (key) के माध्यम से पढ़ता है, और स्कोप समाप्त होने पर बाइंडिंग गायब हो जाती है; नेस्टेड स्कोप अस्थायी रूप से रीबाइंड कर सकते हैं, जबकि Carrier इम्यूटेबल और थ्रेड-सेफ है। यह वर्चुअल-थ्रेड और स्ट्रक्चर्ड-कॉनकरेंसी कोड को म्यूटेबल ThreadLocal की तुलना में अधिक सख्त लाइफटाइम देता है, लेकिन यह उस स्टेट के लिए नहीं है जिसे स्कोप्स के पार लिखा जाना चाहिए। माइग्रेशन के दौरान स्पष्ट पैरामीटर और बाउंड्री टेस्ट बनाए रखें।
गहराई से उत्तर, चरण दर चरण
1. कॉन्टेक्स्ट की (Key) को परिभाषित करें
एक प्राइवेट ScopedValue की का उपयोग करें और ट्रेस आईडी, टेनेंट आईडी, और प्रिंसिपल को एक इम्यूटेबल Context में रखें। डीप कोड के लिए म्यूटेबल मैप या राइटेबल सेशन ऑब्जेक्ट को एक्सपोज़ न करें।
2. एक लेक्सिकल स्कोप बनाएं
static final ScopedValue<RequestContext> REQUEST = ScopedValue.newInstance();
ScopedValue.where(REQUEST, context).run(() -> handle(request));handle के अंदर डीप कॉल्स वर्तमान बाइंडिंग को पढ़ सकते हैं, लेकिन स्कोप समाप्त होने के बाद यह विज़िबल नहीं होता है। लाइफटाइम थ्रेड रिक्लेमेशन के बजाय कोड ब्लॉक का अनुसरण करता है।
3. पढ़ना और अनुपस्थिति (Absence) को संभालना
जब अनुपस्थिति मान्य हो तो isBound() का उपयोग करें, या एक स्पष्ट आंतरिक डिफॉल्ट के लिए orElse का उपयोग करें। सिक्योरिटी प्रिंसिपल जैसे आवश्यक कॉन्टेक्स्ट को चुपचाप अज्ञात (anonymous) के रूप में चलने के बजाय orElseThrow का उपयोग करना चाहिए।
4. Carrier की व्याख्या करें
ScopedValue.Carrier एक इम्यूटेबल, थ्रेड-सेफ की-वैल्यू मैपिंग है; where को चेन करने पर एक नया कैरियर वापस मिलता है। कई बाइंडिंग्स को असेंबल करें और run या call को इन्वोक करें; म्यूटेबल कैरियर को साझा न करें।
5. नेस्टेड रीबाइंडिंग को संभालना
एक इनर where उसी की के लिए अस्थायी रूप से एक नया मान बाइंड कर सकता है, जिसके बाद बाहरी मान रीस्टोर हो जाता है। समीक्षा के दौरान स्कोप ट्री बनाएं ताकि कॉलबैक, एक्सेप्शन हैंडलर, और लॉग गलत टेनेंट या प्रिंसिपल को न पढ़ सकें।
6. वर्चुअल थ्रेड्स और स्ट्रक्चर्ड कॉनकरेंसी के साथ संयोजित करें
लेक्सिकल स्कोप के अंदर चाइल्ड टास्क बनाएं ताकि वे इच्छित कॉन्टेक्स्ट स्नैपशॉट प्राप्त कर सकें। कैंसिलेशन या एक्सेप्शनल कम्प्लीशन होने पर भी मैनुअल थ्रेड-लोकल क्लीनअप के बिना स्कोप से बाहर निकल जाता है; दस्तावेज़ित करें कि कौन से चाइल्ड टास्क किसी की को ओवरराइड कर सकते हैं।
7. ThreadLocal से तुलना करें
ThreadLocal उन लेगेसी APIs के लिए उपयुक्त है जिन्हें थ्रेड एसोसिएशन और म्यूटेबल राइट्स की आवश्यकता होती है, लेकिन पूल रीयूज़ के कारण क्लीनअप भूलना आसान हो जाता है। ScopedValue रीड-ओनली, शॉर्ट-लिव्ड, रेस्ट्रिक्टेड विज़िबिलिटी का समर्थन करता है और हर ThreadLocal को प्रतिस्थापित नहीं कर सकता है, विशेष रूप से उस स्टेट को जिसे कॉलबैक्स के बीच संशोधित किया जाना चाहिए।
8. माइग्रेशन और ऑब्जर्वेबिलिटी की योजना बनाएं
कॉन्टेक्स्ट स्कीमा, अनुमत पाठकों (readers), और JDK मैट्रिक्स को परिभाषित करें, फिर एक एडेप्टर का उपयोग करें ताकि पुराना कोड धीरे-धीरे माइग्रेट हो सके। अनबाउंड विफलताओं, थ्रेड सीमाओं, नेस्टेड ओवरराइड्स, और रिक्वेस्ट पूरा होने के बाद रखे गए संदर्भों को रिकॉर्ड करें ताकि इम्प्लिसिट कॉन्टेक्स्ट एक अदृश्य ग्लोबल न बन जाए।
ट्रेड-ऑफ और सीमाएं
ScopedValue एक बाइंडिंग संदर्भ पास करता है; यदि मान म्यूटेबल है, तो डेटा रेस और प्रिविलेज परिवर्तन अभी भी संभव हैं। यह स्वचालित रूप से मनमाने नए थ्रेड्स को व्यावसायिक सिमेंटिक्स नहीं देता है और स्पष्ट पैरामीटर, ऑथेंटिकेशन पॉलिसी, या कैंसिलेशन प्रोटोकॉल को प्रतिस्थापित नहीं करता है। पुराने रिलीज़ के लिए कम्पैटिबिलिटी पाथ रखते हुए, स्पष्ट JDK बेसलाइन और स्ट्रक्चर्ड-कॉनकरेंसी मॉडल के साथ Java 25 API को अपनाएं।
रोलआउट योजना और प्रमाण
- मौजूदा ThreadLocal कीज़, राइटर्स, क्लीनअप, और थ्रेड सीमाओं की सूची बनाएं।
- रीड-ओनली रिक्वेस्ट कॉन्टेक्स्ट के लिए ScopedValue कीज़ और इम्यूटेबल प्रकार बनाएं।
- रिक्वेस्ट एंट्री पॉइंट्स और स्ट्रक्चर्ड-टास्क निर्माण को
where(...).run/callके साथ रैप करें। - नेस्टेड रीबाइंडिंग, एक्सेप्शन्स, कैंसिलेशन, वर्चुअल थ्रेड्स, पूल रीयूज़, और अनबाउंड एक्सेस का परीक्षण करें।
- रिलीज़ साक्ष्य के रूप में
ScopedValue,Carrier, एक्सेस कंट्रोल, और स्ट्रक्चर्ड कॉनकरेंसी पर Oracle के Java 25 API मार्गदर्शन का उपयोग करें।
सामान्य गलतियाँ और फॉलो-अप
गलती 1: ScopedValue को एक म्यूटेबल ग्लोबल के रूप में मानना
की विज़िबिलिटी को नियंत्रित करती है, लेकिन बाउंड ऑब्जेक्ट अभी भी म्यूटेबल हो सकता है। इम्यूटेबल कॉन्टेक्स्ट का उपयोग करें और राइट्स को प्रतिबंधित करें।
गलती 2: स्कोप सीमा को भूल जाना
स्कोप से बाहर निकलने के बाद पढ़ना विफल हो जाता है या एक बाहरी बाइंडिंग लौटाता है। एंट्री पॉइंट्स, कॉलबैक्स, और एसिंक्रोनस टास्क निर्माण को स्पष्ट रूप से पहचानें।
गलती 3: हर ThreadLocal को सीधे बदलना
क्रॉस-स्कोप राइट्स और पुराने JDK समर्थन की अलग-अलग बाधाएं हैं। उपयोगों को वर्गीकृत करें, फिर पहले केवल रीड-ओनली रिक्वेस्ट कॉन्टेक्स्ट को माइग्रेट करें।
गलती 4: यह मान लेना कि प्रत्येक थ्रेड स्वचालित रूप से इनहेरिट करता है
कॉन्टेक्स्ट प्रोपेगेशन को टास्क निर्माण, एक्ज़ीक्यूटर्स, और स्ट्रक्चर्ड कॉनकरेंसी के साथ डिज़ाइन किया जाना चाहिए; थ्रेड का नाम कोई प्रोपेगेशन कॉन्ट्रैक्ट नहीं है।
गलती 5: प्रिंसिपल ओवरराइड्स को अनदेखा करना
नेस्टेड रीबाइंडिंग ऑडिट पहचान को बदल सकती है। प्रिंसिपल को इम्यूटेबल रखें, आवश्यकता पड़ने पर इसे अनिवार्य बनाएं, और ओवरराइड्स का ऑडिट करें।