2012-11-20 24 views
5

में कार्यों को वापस रखने का कोई तरीका है मेरे पास Executor द्वारा निष्पादित किए जाने वाले कार्यों की एक श्रृंखला है (यानी Runnable एस)।
प्रत्येक कार्य को आगे बढ़ने के लिए एक निश्चित शर्त वैध होने की आवश्यकता होती है। मुझे यह जानने में दिलचस्पी होगी कि कतार के अंत में कार्यों को स्थानांतरित करने के लिए किसी भी तरह Executor को कॉन्फ़िगर करने का कोई तरीका है और स्थिति को वैध होने पर और बाद में निष्पादित करने में सक्षम होने पर उन्हें निष्पादित करने का प्रयास करें।
तो व्यवहार हो की तरह कुछ: हालत अभी तक मान्य क्या एक्जिक्यूटर कतार

  • टास्क नहीं है कतार से

    1. Thread-1 ले कार्यों और run
    2. run अंदर
    3. कहा जाता है बंद हो जाता है और कतार के अंत में Thread-1 स्थानों कार्य और को
    4. निष्पादित करने के लिए अगला कार्य मिलता है बाद में Thread-X (थ्रेड पूल से) कतार की स्थिति से फिर से कार्य करता है वैध और कार्य हो रहा है निष्पादित
  • +0

    बस एक नया कार्य बनाएं जो वर्तमान के बराबर है और इसे कतार में डाल दें। वर्तमान कार्य को समाप्त करें – hoaz

    +0

    @hoaz: क्या आप निष्पादक को कार्यों के अंदर से संदर्भित करते हैं? – Cratylus

    +1

    @ क्रेटिलस - हाँ, यदि कार्य में निष्पादक को संदर्भ दिया गया है, तो यह स्वयं को फिर से कतारबद्ध कर सकता है। बस सुनिश्चित करें कि निष्पादक की लंबित कार्य कतार असंबद्ध है या आप अपने आप को मृत-लॉकिंग समाप्त कर सकते हैं। – jtahlborn

    उत्तर

    2

    पहले निष्पादक बनाएं।

    आपके पास कई संभावनाएं हैं।

    यदि मुझे लगता है कि आपके कार्य उनकी स्थिति ('NeedReschedule' या 'Completed' के साथ एक enum की तरह कुछ करने के लिए एक सरल इंटरफ़ेस लागू करते हैं), तो अपने कार्यों के लिए एक रैपर लागू करें (Runnable लागू करना) जो कार्य करेगा और निष्पादन पैरामीटर के रूप में निष्पादक। यह रैपर उस कार्य को चलाएगा जो इसे बाध्य करता है, बाद में इसकी स्थिति की जांच करें, और यदि आवश्यक हो तो निष्पादक में स्वयं की प्रतिलिपि स्वयं की एक प्रतिलिपि करें।

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

    अपवाद सिग्नलिंग तंत्र का उपयोग करके रैपर का एक संभावित कार्यान्वयन यहां दिया गया है। आपको RescheduleException कक्षा Throwable तक विस्तारित करने की आवश्यकता है, जिसे लपेटा हुआ रननेबल (इस सेटअप में कार्य के लिए अधिक विशिष्ट इंटरफ़ेस की आवश्यकता नहीं है) द्वारा निकाल दिया जा सकता है। आप एक अन्य उत्तर में प्रस्तावित एक सरल RuntimeException का भी उपयोग कर सकते हैं, लेकिन आपको यह जानने के लिए संदेश स्ट्रिंग का परीक्षण करना होगा कि यह अपवाद है जिसका आप इंतजार कर रहे हैं।

    public class TaskWrapper implements Runnable { 
    
        private final ExecutorService executor; 
        private final Runnable task;  
    
        public TaskWrapper(ExecutorService e, Runnable t){ 
         executor = e; 
         task = t; 
        } 
    
    @Override 
    public void run() { 
    
        try { 
           task.run(); 
        } 
        catch (RescheduleException e) { 
         executor.execute(this); 
        } 
    } 
    

    यहाँ एक बहुत ही सरल 200 लिपटे कार्यों बेतरतीब ढंग से ऊपर फायरिंग आवेदन एक पुनर्निर्धारित पूछ है।

    class Task implements Runnable { 
    
        @Override 
        public void run(){ 
        if (Maths.random() > 0.5) 
         throw new RescheduleException(); 
        }  
    } 
    
    
    public class Main { 
    
    public static void main(String[] args){ 
    
        ExecutorService executor = Executors.newFixedThreadPool(10); 
    
        int i = 200; 
          while(i--) 
         executor.execute(new TaskWrapper(executor, new Task()); 
    } 
    } 
    

    तुम भी एक समर्पित धागा अन्य थ्रेड परिणाम (एक संदेश कतार का उपयोग) पर नजर रखने और पुनर्निर्धारित यदि आवश्यक हो सकता है, लेकिन आप अन्य समाधान की तुलना में एक धागा खो देते हैं,।

    +0

    क्या आप कृपया अपने सुझावों पर थोड़ा और विवरण दे सकते हैं? – Cratylus

    +0

    'यह रैपर उस कार्य को चलाएगा जो इसे बाध्य करता है, इसके बाद की स्थिति की जांच करें। कैसे?' कॉल करने योग्य 'का उपयोग करना? – Cratylus

    +0

    एक सरल कार्यान्वयन प्रदान किया गया (कोड परीक्षण नहीं किया गया)। – didierc

    3

    जावा 6 में, ThreadPoolExecutor कन्स्ट्रक्टर BlockingQueue<Runnable> लेता है, जिसका उपयोग कतारबद्ध कार्यों को संग्रहीत करने के लिए किया जाता है। आप ऐसी अवरोधक कतार को कार्यान्वित कर सकते हैं जो poll() को ओवरराइड करता है ताकि यदि "तैयार" नौकरी को निकालने और निष्पादित करने का प्रयास किया गया है, तो poll सामान्य के रूप में प्राप्त होता है।अन्यथा कतार के पीछे भागने योग्य जगह है और आप कम समय के बाद संभवतः फिर से मतदान करने का प्रयास करते हैं।

    +0

    क्या यह कार्यान्वयन विस्तार पर निर्भर नहीं है? मैं यह सुनिश्चित करने के लिए कैसे जानूं कि कार्यान्वयन * मतदान * का उपयोग करेगा। मैं नहीं चाहता कि यह 'ओरेकल' स्रोत कोड पर आधारित हो, उदाहरण के लिए – Cratylus

    +0

    मुझे नहीं पता कि यह क्या है निश्चित रूप से 'मतदान' का प्रयोग करें। मुझे पता है कि यह 'निकालें() ',' मतदान()', ले() या 'मतदान (समय, इकाई)' में से एक का उपयोग करेगा, क्योंकि दस्तावेज के अनुसार अवरुद्ध कतार से हटाने के लिए ये विधियां हैं। – mbatchkarov

    +0

    इसके अलावा, हालांकि आपका सुझाव आकर्षक है (+1), मैं नहीं देख सकता कि यह कैसे मदद करेगा। चेक के तहत स्थिति कुछ वैश्विक स्थिति नहीं है, यह 'रन' के दौरान 'रननेबल' की स्थिति का हिस्सा है। – Cratylus

    3

    जब तक आपको व्यस्त इंतजार न करना पड़े, तो आप एक उचित मतदान अंतराल के साथ एक दोहराए गए कार्य को जोड़ सकते हैं जिसे आप रद्द या मारने के बाद "वैध" चलाने के बाद मार सकते हैं।

    ScheduleExecutorService ses = ... 
    
    ses.scheduleAtFixedRate(new Runnable() { 
        public void run() { 
         if (!isValid()) return; 
         preformTask(); 
         throw new RuntimeException("Last run"); 
        } 
    }, PERIOD, PERIOD, TimeUnit.MILLI_SECONDS); 
    
    +0

    के लिए स्थानीय है' के लिए 'रनटाइम अपवाद' क्या है? – Cratylus

    +0

    कार्य दोहराने को रोकने का सबसे आसान तरीका है। विकल्प हैं लेकिन वे कम से कम बदसूरत और अधिक जटिल हैं। –

    +0

    अपवाद कतार में अगले कार्यों को प्रभावित नहीं करेगा, है ना? – Cratylus