2010-03-26 12 views
5

मुझे लगता है कि यह बहुप्रचारित जावा अनुप्रयोगों के लिए एक आम परिदृश्य है, इसलिए मैं इसे यहां वर्णित करने का प्रयास करूंगा।
जावा मल्टीथ्रेडेड ऐप - फ्यूचर्स ऑब्जेक्ट्स को गतिशील रूप से रद्द करने के लिए कैसे करें

मेरे जावा ऐप में मेरे पास थ्रेडएक्सएटर ऑब्जेक्ट है जो 5 थ्रेड के पूल को परिभाषित करता है।

ExecutorService threadExecutor = Executors.newFixedThreadPool(5); 

एक sendCallables विधि निर्वाहक के कार्यों की सूची आवंटित करने के लिए जिम्मेदार है।
मैं सूची का ट्रैक ऑब्जेक्टएक्स के साथ ट्रैक रखता हूं। यदि उपयोगकर्ता थ्रेड को बाधित/रद्द करना चाहता है तो इस तरह से मैं फ्यूचर्स की सूची का संदर्भ दे सकता हूं। कुछ ऐसा:

Map<ObjectX, List<Future<String>>> map = new HashMap<ObjectX, Future<String>>(); 

public void sendCallables(ObjectX referenceObj, List<Callable<String>> list) { 
    ... 
    List<Future<String>> futureList = new ArrayList<Future<String>>(); 
    for(Callable<String> myCallableJob : list) { 
     Future<String> future = threadExecutor.submit(myCallableJob); 
     futureList.add(future); 
    } 
    ... 
    map.add(referenceObj, futureList); 
    ... 
} 

public void cancelFutures(ObjectX referenceObj) { 
    ... 
    List<Future<String>> list = map.get(referenceObj); 
    for(Future<String> future : list) { 
     future.cancel(); 
    } 
    map.remove(referenceObj); 
    .... 
} 

अब तक इतना अच्छा है।

अब ऐसे मामले हैं जब सबमिट किए गए कार्यों को निष्पादित करने की आवश्यकता नहीं है
इन स्थितियों में कार्यों को रद्द करने का निर्णय आवेदन द्वारा समझदारी से/स्वचालित रूप से लिया जाना चाहिए।
ऐसे मामलों के उदाहरण किसी वेब एप्लिकेशन में पाए जा सकते हैं जब उपयोगकर्ता का सत्र समाप्त हो जाता है या जब सभी नौकरियां निष्पादित होने से पहले विशिष्ट फ़्लो (सबमिट किए गए कार्यों से संबंधित) समाप्त होती है।

तो मूल रूप से मुझे हर बार रद्द करने के लिए फ्यूचर्स (संदर्भ ओबीजे) कॉल करने की आवश्यकता होगी कि मेरे आवेदन के लिए नौकरियों को निष्पादित करने के लिए कोई समझ नहीं है। जब मुझे एप्लिकेशन को कॉल करने की आवश्यकता होती है तो मुझे प्रत्येक स्थिति की पहचान करनी होगी।

मुझे आश्चर्य है कि ऐसा करने के लिए एक बेहतर तरीका है या नहीं।

मैं WeakHashMap में सोच रहा था कि संदर्भ को एक बार संदर्भित करने के लिए मानचित्र को साफ करने में सक्षम होने के लिए, लेकिन यह फ़्यूचर्स को निष्पादित करने से रोकता नहीं है क्योंकि मुझे अभी भी कॉल करने की आवश्यकता है। (WeakHashMap हटाने (ऑब्जेक्ट) विधि से जुड़े एक प्रकार का ईवेंट हैंडलर?)

उत्तर

3

मुझे लगता है कि आप जिस समाधान का प्रस्ताव दे रहे हैं वह बहुत अच्छा है। यदि आप वास्तव में, वास्तव में संदर्भ ओबीजे को कचरा प्राप्त करने से रद्दीकरण को ड्राइव करना चाहते हैं तो आप वीक रेफरेंस और रेफरेंस क्यूयू के संयोजन का उपयोग कर सकते हैं।

इनमें से एक को आपके निष्पादन सहायक वर्ग में घोषित किया गया है।

ReferenceQueue<ObjectX> refQ = new ReferenceQueue<ObjectX>(); 

इस हर बार एक कार्य बैच प्रस्तुत की है

new WeakReference<ObjectX>(referenceObj, refQ).enqueue(); 

एक धागा है कि सिर्फ इस पाश जो बंद वस्तुओं खींचती है हो जाता है कि कमजोर-से पहुंचा जा सकता (जीसी के लिए पात्र हैं) चलाता है और रद्द वायदा/कार्य।

while (true) 
{ 
    // this blocks 
    ObjectX referenceObj = refQ.remove().get(); 
    cancelFutures(referenceObj); 
} 
+0

आइडिया तब तक अच्छा है जब तक आप संदर्भ ओबीजे के लिए मजबूत संदर्भ नहीं रखते ... – pgras

+0

धन्यवाद माइक .. मैं इसे आज़मा दूंगा – mickthompson

0

यदि मैं आपकी समस्या को सही ढंग से समझता हूं, तो आपके पास विभिन्न प्रकार की गतिविधियां होती हैं और आप इन गतिविधियों को एक साथ जोड़ना नहीं चाहते हैं क्योंकि उन्हें रद्द किया जा सकता है ।

मेरे लिए यह लगता है कि रद्दीकरण की आवश्यकता वाले प्रत्येक मामले को एक ईवेंट ट्रिगर करना चाहिए। घटना श्रोता इन घटनाओं के लिए सुनेंगे और प्रासंगिक Future रद्द कर देंगे।

सत्रों के बारे में आपका उदाहरण - आपके पास एक कक्षा होगी जो javax.servlet.http.HttpSessionListner लागू करती है, उन प्रासंगिक कार्यों का पता लगाती है जिन्हें रद्दीकरण की आवश्यकता होती है और उन कार्यों को रद्द करने के लिए किसी ईवेंट को आग लगती है। चूंकि सब कुछ अतुल्यकालिक है, आप परवाह नहीं करेंगे कि रद्द किया गया कार्य समाप्त हो गया है या नहीं, इसलिए कुछ भी नहीं खो गया है।

संबंधित मुद्दे