2012-08-11 16 views
10

क्या कोई विशिष्ट थ्रेड रोकने/फिर से शुरू करने के लिए निष्पादक सेवा का उपयोग करने का कोई तरीका है?जावा एक्जिक्यूटर्स सर्विस रोकें/एक विशिष्ट थ्रेड को फिर से शुरू करें

private static ExecutorService threadpool = Executors.newFixedThreadPool(5);

कल्पना कीजिए कि मैं आईडी = 0 (यह सोचते हैं कि करने के लिए हर एक ThreadPool के आकार तक एक वृद्धिशील आईडी निर्दिष्ट नहीं पहुँच जाता है) के रूप में धागा है जो बंद करना चाहते हैं।

थोड़ी देर के बाद, एक बटन दबाकर, मान लें कि, मैं उस विशिष्ट थ्रेड को फिर से शुरू करना चाहता हूं और अन्य सभी धागे को अपनी वर्तमान स्थिति के साथ छोड़ना चाहता हूं, जिसे रोक दिया जा सकता है या फिर से शुरू किया जा सकता है।

मुझे जावा दस्तावेज़ पर PausableThreadPoolExecutor का एक अपूर्ण संस्करण मिला है। लेकिन यह मेरी ज़रूरत के अनुरूप नहीं है क्योंकि यह पूल में सभी धागे को फिर से शुरू करता है।

यदि निष्पादक सेवा के डिफ़ॉल्ट कार्यान्वयन के साथ ऐसा करने का कोई तरीका नहीं है तो क्या कोई मुझे इस समस्या के लिए जावा कार्यान्वयन के लिए इंगित कर सकता है?

धन्यवाद!

+0

आपको यकीन है?दिए गए आईडी के साथ थ्रेड कुछ यादृच्छिक रूप से चुने गए नौकरी निष्पादित करता है, इसलिए आप कुछ अज्ञात नौकरी रोक रहे हैं। ऐसा करने का अर्थ क्या है? –

+0

निम्न स्थिति की कल्पना करें: आपके पास एक डाउनलोड प्रबंधक है, और उस प्रबंधक पर आप डाउनलोड को रोक और फिर से शुरू कर सकते हैं। प्रत्येक के लिए आप सामान डाउनलोड कर रहे हैं, इससे कोई फर्क नहीं पड़ता कि प्रासंगिक नहीं है, और आप जहां भी चाहें उस डाउनलोड को फिर से शुरू करना चाहते हैं। क्या यह सवाल आपको अधिक स्पष्ट करता है? –

+0

अधिक स्पष्ट, लेकिन अभी भी ज्यादा समझ में नहीं आता है। डाउनलोड रोकें/फिर से शुरू करें व्यवसाय तर्क के बारे में है, जबकि थ्रेडपूल कम्प्यूटेशनल संसाधनों के बारे में है। संसाधनों को जोड़ने/निकालने के द्वारा तर्क को नियंत्रित करने के लिए IMHO एक बुरा विचार है। –

उत्तर

7

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

अद्यतन करने में रुचि होगी:
उचित तरीके से करने के लिए थ्रेड पूल में सबमिट किया गया अपना कार्य रद्द करें निष्पादक द्वारा दिए गए कार्य के लिए Future के माध्यम से है।
1) इस तरह से आप यह सुनिश्चित करें कि आप वास्तव में उद्देश्य कार्य
2 रद्द कर दिया करने का प्रयास किया जाता है) के लिए पता है अपने कार्यों को पहले से ही रद्द करने योग्य होने के लिए तैयार कर रहे हैं, तो आपके वहाँ आधे रास्ते
3) एक ध्वज का उपयोग न करें हैं रद्द करने से संकेत मिलता है लेकिन उपयोग करने के लिए Thread.currentThread().interrupt() बजाय

अद्यतन:

public class InterruptableTasks { 

    private static class InterruptableTask implements Runnable{ 
     Object o = new Object(); 
     private volatile boolean suspended = false; 

     public void suspend(){   
      suspended = true; 
     } 

     public void resume(){  
      suspended = false; 
      synchronized (o) { 
       o.notifyAll(); 
      } 
     } 


     @Override 
     public void run() { 

      while(!Thread.currentThread().isInterrupted()){ 
       if(!suspended){ 
        //Do work here  
       } 
       else{ 
        //Has been suspended 
        try {     
         while(suspended){ 
          synchronized(o){ 
           o.wait(); 
          }       
         }      
        } 
        catch (InterruptedException e) {      
        }    
       }       
      } 
      System.out.println("Cancelled");   
     } 

    } 

    /** 
    * @param args 
    * @throws InterruptedException 
    */ 
    public static void main(String[] args) throws InterruptedException { 
     ExecutorService threadPool = Executors.newCachedThreadPool(); 
     InterruptableTask task = new InterruptableTask(); 
     Map<Integer, InterruptableTask> tasks = new HashMap<Integer, InterruptableTask>(); 
     tasks.put(1, task); 
     //add the tasks and their ids 

     Future<?> f = threadPool.submit(task); 
     TimeUnit.SECONDS.sleep(2); 
     InterruptableTask theTask = tasks.get(1);//get task by id 
     theTask.suspend(); 
     TimeUnit.SECONDS.sleep(2); 
     theTask.resume(); 
     TimeUnit.SECONDS.sleep(4);     
     threadPool.shutdownNow();  
    } 
+0

क्या आप अधिक विशिष्ट हो सकते हैं और मुझे एक वास्तविक कार्यान्वयन या उदाहरण प्रदान कर सकते हैं? मैंने वास्तव में इसकी सराहना की, क्योंकि मैं इस समस्या से काफी लंबे समय से संघर्ष कर रहा हूं। –

+0

@ रिकार्डो सैंटोस: लेकिन आप अपने कार्यों को रद्द करने योग्य क्यों नहीं बनाते हैं? आपके कोड के सीधे – Cratylus

+0

धागे से बातचीत करना अच्छा नहीं है, मैं कार्यों को रद्द करने की सिफारिश के साथ सहमत हूं। ओपी ने लिखा "कल्पना करें कि मैं थ्रेड आईडी = 0 रोकना चाहता हूं"। यह ज्यादा समझ में नहीं आता है, क्योंकि किसी भी समय आप नहीं जानते कि थ्रेड 0 क्या कर रहा है। लेकिन वर्तमान में कुछ काम रोकने के बारे में बात करना समझ में आता है, इसलिए कार्यों को रद्द करने की सिफारिश। –

4

सुझाव: इसी प्रकार/झंडे का उपयोग कर रहे करने के बजाय, एक semaphore 1 के साथ परमिट (new Semaphore(1)) बनाने के लिए के लिए प्रत्येक कार्य को रोकें/रोकें।

semaphore.acquire(); 
semaphore.release(); 

यह एक सेमाफोर परमिट प्राप्त करने और तुरंत इसे जारी करने की कार्य का कारण बनता है: काम के काम चक्र की शुरुआत में इस तरह की एक कोड डाल दिया। अब अगर आप थ्रेड को रोकना चाहते हैं (उदाहरण के लिए बटन दबाया जाता है), तो semaphore.acquire() को किसी अन्य थ्रेड से कॉल करें। चूंकि सेमफोर के पास अब परमिट है, इसलिए आपका कामकाजी धागा अगले चक्र की शुरुआत में रुक जाएगा और जब तक आप अन्य थ्रेड से semaphore.release() पर कॉल नहीं करेंगे तब तक प्रतीक्षा करें।

(acquire() विधि InterruptedException फेंकता है, अपने काम धागा प्रतीक्षा करते हुए बाधित हो जाता है। वहाँ एक और तरीका acquireUninterruptibly() है, जो भी एक परमिट प्राप्त करने के लिए कोशिश करता है, लेकिन बाधित न हो।)

+0

बंद हो जाता है यकीन है कि यह नौकरी करता है लेकिन एक हैक की तरह लगता है और यह कुछ भी करने से बेहतर तरीका है। तो उत्तर देने के लिए धन्यवाद। मैं आपके दृष्टिकोण और @ user384706 का परीक्षण करूँगा और देखें कि किसके पास बेहतर प्रदर्शन है। –

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