प्रॉम्प्ट और दायरा
एक साक्षात्कारकर्ता पूछ सकता है: “Java 25 ScopedValue किस समस्या का समाधान करता है? इसकी तुलना ThreadLocal से करें और थ्रेड पूल या वर्चुअल थ्रेड्स के साथ इसके सही उपयोग की व्याख्या करें।”
JEP 506 ने JDK 25 में Scoped Values को अंतिम रूप दिया। वे एक कॉलर को लेक्सिकल स्कोप के भीतर डीप कॉलीज़ और चाइल्ड थ्रेड्स के साथ अपरिवर्तनीय (immutable) डेटा साझा करने की अनुमति देते हैं, जिससे प्रत्येक मेथड पैरामीटर के माध्यम से संदर्भ (context) पास करने की आवश्यकता कम हो जाती है। यह प्रश्न लाइफटाइम, दृश्यता और समवर्ती (concurrency) सीमाओं का परीक्षण करता है; ScopedValue को केवल “एक नया ThreadLocal” कहकर इसका उत्तर नहीं दिया जा सकता है।
साक्षात्कारकर्ता क्या परीक्षण कर रहा है
- क्या आप ScopedValue को एक अपरिवर्तनीय, स्कोप-नियंत्रित अंतर्निहित (implicit) पैरामीटर के रूप में समझते हैं।
- क्या आप
where(...).run(...)याcall(...)के बाइंडिंग और रीस्टोरेशन की व्याख्या कर सकते हैं। - क्या आप म्यूटेबल ThreadLocal, पूल्ड-थ्रेड पुनर्चक्रण (reuse), और वर्चुअल-थ्रेड इनहेरिटेंस से अंतर को पहचानते हैं।
- क्या आप की (key) एक्सेस नियंत्रण, बाइंडिंग संख्या, अपवाद प्रसार (exception propagation), और रद्दीकरण (cancellation) पर विचार करते हैं।
- क्या आप जानते हैं कि स्पष्ट पैरामीटर या ThreadLocal कब उपयुक्त बने रहते हैं।
स्पष्टीकरण के लिए प्रश्न
- क्या साझा किया गया मान एक अनुरोध आईडी (request ID), प्रिंसिपल, टेनेंट, या म्यूटेबल ट्रांजेक्शन स्थिति है?
- क्या इसे केवल-पढ़ने के लिए (read-only) होना चाहिए, और क्या चाइल्ड कार्यों को इसे इनहेरिट करना चाहिए?
- क्या निष्पादन प्लेटफ़ॉर्म थ्रेड्स, वर्चुअल थ्रेड्स, स्ट्रक्चर्ड समवर्ती, या मौजूदा पूल पर है?
- क्या कोड अपने स्कोप के बाहर की (key) को पढ़ सकता है या किसी अविश्वसनीय कोड के लिए Carrier को उजागर कर सकता है?
- क्या फ्रेमवर्क ThreadLocal क्लीनअप, म्यूटेशन, या MDC एकीकरण पर निर्भर करता है?
30-सेकंड का उत्तर
आप कह सकते हैं:
ScopedValue Java 25 का अपरिवर्तनीय, लेक्सिकली स्कोप्ड संदर्भ तंत्र है। एक कॉलरScopedValue.where(key, value).run(...)याcall(...)के साथ एक बाइंडिंग बनाता है; स्कोप समाप्त होने पर इसे रीस्टोर किया जाता है, और केवल वही कोड इसे पढ़ सकता है जिसके पास की (key) है। ThreadLocal की तुलना में, यह पूल्ड-थ्रेड क्लीनअप और म्यूटेबल-स्टेट लीक को कम करता है, जिससे यह अनुरोध संदर्भ, वर्चुअल थ्रेड्स और स्ट्रक्चर्ड समवर्ती के लिए उपयोगी हो जाता है। यह उस ThreadLocal को प्रतिस्थापित नहीं करता है जिसे चरण-दर-चरण अपडेट किया जाना चाहिए, और किसी मान को अपने स्कोप से बाहर नहीं निकलना चाहिए। मैं लक्षित JDK पर इनहेरिटेंस, अपवादों, रद्दीकरण और की (key) दृश्यता का परीक्षण करूंगा।
चरण-दर-चरण तर्क
बाइंडिंग मॉडल को समझें
डायनामिक निष्पादन सीमा के दौरान मान पढ़ने योग्य होता है, जबकि बाइंडिंग को कोड संरचना द्वारा स्पष्ट किया जाता है:
static final ScopedValue<String> REQUEST_ID = ScopedValue.newInstance();
ScopedValue.where(REQUEST_ID, "req-42").run(() -> {
audit("start");
handleRequest();
});
static void audit(String message) {
logger.info("{} {}", REQUEST_ID.orElse("missing"), message);
}audit को अनुरोध-आईडी पैरामीटर की आवश्यकता नहीं होती है, लेकिन यह केवल बाइंडिंग स्कोप के अंदर ही एक सार्थक मान पढ़ता है। एक बार स्कोप समाप्त हो जाने के बाद, बाइंडिंग कॉलर थ्रेड को दूषित नहीं कर सकती है।
ThreadLocal परिवर्तनशीलता (mutability) की तुलना करें
ThreadLocal प्रत्येक थ्रेड को एक म्यूटेबल मान देता है; पूल्ड-थ्रेड के पुनर्चक्रण के लिए क्लीनअप की आवश्यकता होती है अन्यथा अगला अनुरोध पुराने संदर्भ को देख सकता है। ScopedValue को अपरिवर्तनीय साझाकरण के लिए डिज़ाइन किया गया है, जिसमें नेस्टेड बाइंडिंग्स होती हैं जो अस्थायी रूप से बाहरी मान को ओवरराइड (shadow) करती हैं और बाद में इसे रीस्टोर करती हैं। यह क्लीनअप की जिम्मेदारी को कम करता है लेकिन ऐसी स्टेट मशीन को नहीं ले जाता है जिसे डीप कोड को बार-बार set करना पड़े।
चाइल्ड कार्यों और वर्चुअल थ्रेड्स को संभालें
JEP 506 वर्चुअल थ्रेड्स और स्ट्रक्चर्ड समवर्ती के साथ पूर्वानुमानित साझाकरण लागतों को लक्षित करता है। इनहेरिटेंस होता है या नहीं, इसे कब कैप्चर किया जाता है, और एक निष्पादक (executor) कैसा व्यवहार करता है, इसे लक्षित JDK और API अनुबंध के विरुद्ध सत्यापित किया जाना चाहिए; साधारण थ्रेड पूल से धारणाओं को स्थानांतरित न करें। साझा की गई वस्तु को अपरिवर्तनीय रहना चाहिए ताकि कोई संदर्भ संदर्भ सीमा को बायपास न कर सके।
की (keys), अपवाद, और अनुकूलता डिज़ाइन करें
एक की (key) को private static final ऑब्जेक्ट या नियंत्रित API का हिस्सा बनाएं। विश्व स्तर पर साझा की गई की (key) को सुरक्षा सीमा के रूप में न मानें। अनुपलब्ध मान के लिए orElse या स्पष्ट अपवाद का उपयोग करें; Java 25 में, orElse अब null स्वीकार नहीं करता है। run या call से बाहर निकलने वाला अपवाद अभी भी स्कोप से बाहर निकलता है और बाहरी बाइंडिंग को रीस्टोर करता है। पुराने JDK के लिए, एक परीक्षित अनुकूलता पथ के पीछे स्पष्ट पैरामीटर या एक ThreadLocal कार्यान्वयन बनाए रखें।
मॉडल उच्च-गुणवत्ता वाला उत्तर
मैं ScopedValue को एक अपरिवर्तनीय अंतर्निहित पैरामीटर के रूप में मानता हूं, न कि ThreadLocal के लिए एक म्यूटेबल प्रतिस्थापन के रूप में। अनुरोध प्रविष्टि बिंदुwhere(key, value).runयाcallके साथ एक संरचित स्कोप बनाता है; डीप मेथड्स की (key) के माध्यम से एक अनुरोध आईडी, टेनेंट, या प्रिंसिपल को पढ़ते हैं, और बाहर निकलने पर बाइंडिंग रीस्टोर हो जाती है। यह वर्चुअल थ्रेड्स और स्ट्रक्चर्ड समवर्ती में केवल-पढ़ने के संदर्भ के लिए उपयुक्त है और पूल्ड-थ्रेड क्लीनअप लीक से बचाता है। ThreadLocal उस स्थिति के लिए उपयोगी बना रहता है जिसे चरण-दर-चरण अपडेट किया जाना चाहिए, जिसमें finally में क्लीनअप शामिल है। मैं की (key) दृश्यता को प्रतिबंधित करूंगा, चाइल्ड-टास्क इनहेरिटेंस, अपवादों, रद्दीकरण, नेस्टेड शैडोइंग, और स्कोप के बाहर पढ़ने का परीक्षण करूंगा, और पुराने JDK के लिए एक स्पष्ट या संगत कार्यान्वयन रखूंगा।
सामान्य गलतियाँ
- ScopedValue को स्वचालित क्लीनअप वाला एक म्यूटेबल ThreadLocal कहना।
- Carrier या मान को स्कोप के बाहर सहेजना, या उसके लाइफटाइम के बाद किसी की (key) को पढ़ना।
- पूल्ड-थ्रेड पुनर्चक्रण, चाइल्ड-टास्क इनहेरिटेंस और वर्चुअल-थ्रेड अंतरों की अनदेखी करना।
- पूरे संदर्भ के अपरिवर्तनीय होने का दावा करते हुए एक म्यूटेबल ऑब्जेक्ट को संग्रहीत करना।
- किसी भी मॉड्यूल में एक की (key) साझा करना और एक्सेस कंट्रोल को एन्क्रिप्शन समझने की गलती करना।
- Java 25 के नॉन-नल
orElseनियम को भूल जाना या पुराने-JDK पथ को छोड़ देना।
अनुवर्ती प्रश्न और उत्तर
1. क्या ScopedValue हर ThreadLocal को प्रतिस्थापित कर सकता है?
नहीं। यह केवल-पढ़ने के लिए, स्कोप-बाउंड संदर्भ के लिए उपयुक्त है। कॉल चेन के माध्यम से अपडेट की जाने वाली स्थिति अभी भी आवश्यक क्लीनअप जिम्मेदारी के साथ ThreadLocal या स्पष्ट पैरामीटर का उपयोग कर सकती है।
2. नेस्टेड बाइंडिंग्स के साथ क्या होता है?
एक आंतरिक स्कोप उसी की (key) के लिए अस्थायी रूप से एक नया मान बांध सकता है; इससे बाहर निकलने पर बाहरी मान रीस्टोर हो जाता है। अपवाद पथ भी स्कोप से बाहर निकलते हैं, इसलिए आंतरिक मान बाहर लीक नहीं होता है।
3. आप समवर्ती इनहेरिटेंस का परीक्षण कैसे करते हैं?
प्लेटफ़ॉर्म थ्रेड्स, वर्चुअल थ्रेड्स, स्ट्रक्चर्ड कार्यों और पूल्ड-थ्रेड पुनर्चक्रण को कवर करें। चाइल्ड कार्यों द्वारा देखे गए मान, रद्दीकरण के बाद क्लीनअप, नेस्टेड शैडोइंग और स्कोप के बाहर पढ़ने की जांच करें। परीक्षण मैट्रिक्स में JDK संस्करण और निष्पादक कॉन्फ़िगरेशन को तय करें।