2009-12-10 17 views
45

मुझे जावा में एक थ्रेड शुरू करने, रोकने और पुनरारंभ करने का कोई तरीका खोजने में वास्तविक समय है।जावा में धागे को कैसे शुरू/बंद/पुनरारंभ करें?

विशेष रूप से, मेरे पास Task.java फ़ाइल में Task (वर्तमान में Runnable लागू करता है) है। मेरा मुख्य आवेदन एक धागे पर इस कार्य को शुरू करने में सक्षम होने की जरूरत है, रोकें (मार) धागा जब यह, और कभी कभी & RESTART धागा मारने की जरूरत है ...

मेरा पहला प्रयास ExecutorService साथ था, लेकिन मैं कर सकते हैं ' ऐसा लगता है कि इसे एक कार्य को पुनरारंभ करने का कोई तरीका नहीं है। जब मैं .shutdownnow() का उपयोग करता हूं तो .execute() पर कोई भी भविष्य कॉल विफल रहता है क्योंकि ExecutorService "शटडाउन" है ...

तो, मैं इसे कैसे पूरा कर सकता हूं?

+0

इस प्रश्न के लिए आप यह भी देख सकते हैं: http://stackoverflow.com/questions/22937592/resume-interrupted-thread – artiethenoble

उत्तर

39

एक बार थ्रेड बंद हो जाने पर आप इसे पुनरारंभ नहीं कर सकते हैं। हालांकि, नया धागा बनाने और शुरू करने से आपको रोक नहीं है।

विकल्प 1: पुनरारंभ करने की कोशिश करने के बजाय एक नया धागा बनाएं।

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

संपादित करें टिप्पणी के आधार पर:

"मारने" के लिए धागा आप निम्नलिखित की तरह कुछ कर सकते हैं।

yourThread.setIsTerminating(true); // tell the thread to stop 
yourThread.join(); // wait for the thread to stop 
+0

दुख की बात है कि मुझे इसे मारना/पुनरारंभ करना होगा ... मेरे पास सामग्री पर पूर्ण नियंत्रण नहीं है धागे के लिए और मेरी स्थिति के लिए इसे पुनरारंभ करने की आवश्यकता है ... तो, एक नया निर्माण करना ठीक है ... लेकिन मैं पहले वर्तमान को कैसे मारूं? – Shaitan00

+0

यदि आप सचमुच 'मारना' चाहते थे तो थ्रेड कभी भी भरोसा नहीं करते या किसी भी एपीआई विधियों का उपयोग करने का प्रयास नहीं करते हैं, उदाहरण के लिए मारें() रोकें() नष्ट करें()। इसके बजाए, जैसा कि टेलर ने बाधित फ्लैग को देखने का सुझाव दिया: जबकि (! थ्रेड.currentThread()। अंतर्निहित()) {...} जब थ्रेड बाधित होता है, उस थ्रेड में किसी भी फ़ंक्शन को साफ़ करें और बाहर से वापस आएं रन विधि और एक नया धागा शुरू करें। –

+0

मुझे लगता है कि आपके धागे में एक लूप है ताकि यह देखने के लिए ध्वज की जांच कर सके कि थ्रेड को रोकना चाहिए या निष्पादन जारी रखना चाहिए या नहीं। –

0

धागे को रोकने और रोकने/मारने के बीच एक अंतर है। यदि आपके लिए रोकना मतलब है धागे को मारना, तो फिर से शुरू करना मतलब है कि एक नया धागा बनाना और लॉन्च करना।

एक अलग थ्रेड (जैसे, आपके स्पॉनर) से धागे को मारने के तरीके हैं, लेकिन वे सामान्य रूप से असुरक्षित हैं। यह सुरक्षित हो सकता है यदि आपका धागा लगातार यह देखने के लिए कुछ ध्वज जांचता है कि यह जारी रखना चाहिए (मुझे लगता है कि आपके धागे में कुछ लूप है), और बाहरी "नियंत्रक" उस ध्वज की स्थिति को बदलता है।

आप में एक छोटे से अधिक देख सकते हैं: http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

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

0

यदि आपका कार्य लूप में किसी प्रकार की कार्रवाई कर रहा है, तो प्रसंस्करण को रोकने/पुनरारंभ करने का एक तरीका है, लेकिन मुझे लगता है कि यह वर्तमान में थ्रेड एपीआई द्वारा प्रदान किए जाने वाले बाहर होना होगा। यदि यह एक एकल शॉट प्रक्रिया है, तो मुझे एपीआई में चलाने के बिना निलंबित/पुनरारंभ करने के किसी भी तरीके से अवगत नहीं है जिसे बहिष्कृत किया गया है या अब अनुमति नहीं है।

लूप प्रक्रियाओं के लिए, सबसे आसान तरीका यह है कि मैं सोच सकता हूं कि कार्य उत्पन्न करने वाला कोड एक पुनर्विक्रेता लॉक को तुरंत चालू करता है और इसे कार्य में पास करता है, साथ ही संदर्भ को स्वयं भी रखता है। जब भी कार्य अपने लूप में प्रवेश करता है तो यह ReentrantLock इंस्टेंस पर लॉक का प्रयास करता है और जब लूप पूरा करता है तो उसे अनलॉक करना चाहिए। आप इस प्रयास को अंततः समाहित करना चाहते हैं, अंत में, सुनिश्चित करें कि आप लूप के अंत में लॉक को छोड़ दें, भले ही कोई अपवाद फेंक दिया जाए।

यदि आप कार्य को रोकना चाहते हैं तो बस मुख्य कोड से लॉक का प्रयास करें (क्योंकि आपने संदर्भ को आसान रखा है)। यह क्या करेगा लूप को पूरा करने के लिए प्रतीक्षा करें और इसे एक और पुनरावृत्ति शुरू करने दें (क्योंकि मुख्य धागा लॉक पकड़ रहा है)। धागे को पुनरारंभ करने के लिए बस मुख्य कोड से अनलॉक करें, यह कार्य को अपने लूप को फिर से शुरू करने की अनुमति देगा।

धागे को स्थायी रूप से रोकने के लिए मैं सामान्य एपीआई का उपयोग करता हूं या कार्य में ध्वज छोड़ देता हूं और ध्वज के लिए एक सेटटर (कुछ रोकने के लिए तत्काल)। जब लूप को इस ध्वज के लिए एक वास्तविक मूल्य का सामना करना पड़ा तो यह प्रसंस्करण रोकता है और रन विधि को पूरा करता है।

+0

अफसोस की बात है कि थ्रेड आने वाले ट्रैफिक के लिए प्रतीक्षा कर रहा है (सुनना), यह एक अवरुद्ध सिंक्रोनस इवेंट है ... इसलिए कोई "लूप" – Shaitan00

7

समीक्षा java.lang.Thread

शुरू करने के लिए या पुनः आरंभ (एक बार एक धागा बंद कर दिया है, तो आप कि एक ही धागे को पुनः आरंभ नहीं कर सकता है, लेकिन यह कोई फर्क नहीं पड़ता, बस एक नया Thread उदाहरण बनाने):

// Create your Runnable instance 
Task task = new Task(...); 

// Start a thread and run your Runnable 
Thread t = new Thread(task); 

इसे रोकने के लिए, अपने Task उदाहरण पर एक विधि है जो बाहर निकलने के लिए run विधि बताने के लिए ध्वज सेट करता है; run से लौटने से धागे निकलता है। अपने फोन कोड धागा वास्तव में इससे पहले कि यह रिटर्न बंद कर दिया है पता करने की जरूरत है, तो आप join उपयोग कर सकते हैं:

// Tell Task to stop 
task.setStopFlag(true); 

// Wait for it to do so 
t.join(); 

पुनरारंभ के बारे में: हालांकि एक Thread पुनः प्रारंभ नहीं किया जा सकता है, आप एक नया के साथ अपने Runnable उदाहरण पुन: उपयोग कर सकते हैं धागा अगर यह राज्य है और आप रखना चाहते हैं; यह एक ही बात पर आता है। बस सुनिश्चित करें कि आपका Runnable कई कॉल को run पर अनुमति देने के लिए डिज़ाइन किया गया है।

+0

अफसोस की बात है कि थ्रेड आने वाले ट्रैफिक के लिए प्रतीक्षा (सुनना) है, यह एक अवरुद्ध सिंक्रोनस ईवेंट है .. इसलिए रन के भीतर कोई "लूप" नहीं है ... – Shaitan00

+2

@ शैतान 00: यदि आप 'स्वीकृति' कॉल पर 'सर्वरस्केट' अवरुद्ध करने के बारे में बात कर रहे हैं, तो बस सॉकेट पर अपना 'सेटस्टॉपफ्लैग' कॉल 'क्लोज़' रखें। 'स्वीकृति' कॉल 'सॉकेटएक्सप्शन' फेंक कर अनब्लॉक कर देगा। कुछ भी जो ब्लॉक करता है लगभग निश्चित रूप से एक समान निकास मोड होगा। –

1

जैसा कि टेलर एल द्वारा बताया गया है, आप इस तथ्य के कारण एक थ्रेड (एक साधारण विधि को कॉल करके) "थ्रेड" नहीं कर सकते हैं क्योंकि यह आपके सिस्टम को अस्थिर स्थिति में छोड़ सकता है क्योंकि बाहरी कॉलिंग थ्रेड को पता नहीं हो सकता है कि क्या आपके धागे के अंदर जा रहा है।

इस बात के साथ, धागे को "रुकने" का सबसे अच्छा तरीका यह है कि धागा स्वयं पर नजर रखे और उसे पता चल जाए और समझें कि इसे कब रोकना चाहिए।

+0

लेकिन धागा स्वयं नेटवर्क ट्रैफिक के लिए एक सुनवाई पर अवरुद्ध कर रहा है ... यह वास्तव में कुछ नहीं प्राप्त होने तक लूप नहीं करता है .... तो, इसे "गियर में लूप लातें" के लिए एक डमी संदेश भेजें और एक झंडा सेट करें? – Shaitan00

3

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

ये दो लेख Swing Worker और Concurrency आपकी समस्या के लिए सबसे अच्छा समाधान निर्धारित करने में आपकी सहायता कर सकते हैं।

+0

@ चाडएनसी- यह अच्छा लगता है। क्या आप ऑब्जेक्ट की वर्तमान स्थिति को सहेजने और फिर जारी रखने के बारे में मुझे और मार्गदर्शन कर सकते हैं। – user2821894

8

तब तक थ्रेड को समाप्त करना असंभव है जब तक उस थ्रेड में चलने वाला कोड जांचता है और समाप्त करने की अनुमति देता है।

आप ने कहा, "दुर्भाग्य से मैं मारना चाहिए/उसे पुन: प्रारंभ ... मैं धागे की और मेरी स्थिति के लिए सामग्री पर पूरा नियंत्रण नहीं है यह एक पुनः आरंभ करने की आवश्यकता है"

थ्रेड की सामग्री हैं इसके निष्कर्ष को समाप्त करने की अनुमति नहीं देता है तो आप उस धागे को समाप्त नहीं कर सकते हैं।

अपनी पोस्ट में आप ने कहा: "मेरे पहले प्रयास ExecutorService साथ था, लेकिन मैं एक तरह से पता लगाने के लिए यह एक काम जब मैं .shutdownnow का उपयोग() ... पुनः आरंभ करने के लिए प्रतीत नहीं कर सकते।"

आप तो "शटडाउन" के स्रोत को देखें, यह अभी चल रहा है और वर्तमान में चल रहे धागे को बाधित करता है।यह उनके निष्पादन को तब तक नहीं रोकेगा जब तक कि उन धागे में कोड यह देखने के लिए जांच नहीं करता है कि यह निष्क्रिय है या नहीं, और यदि ऐसा है, तो निष्पादन स्वयं रोकता है। तो शटडाउनो शायद आप जो सोचते हैं वह नहीं कर रहा है।

myExecutor.execute(new Runnable() { 
public void run() { 
    while (true) { 
    System.out.println("running"); 
    } 
} 
}); 
myExecutor.shutdownnow(); 

कि धागा हमेशा के लिए चलना जारी रहेगा, भले ही shutdownnow बुलाया गया था, क्योंकि:

मुझे उदाहरण देकर स्पष्ट करना है कि मैं क्या मतलब है जब मैं कहता हूँ कि थ्रेड की सामग्री के लिए कि धागा समाप्त किया जा करने की अनुमति चाहिए चलो यह कभी भी यह देखने के लिए जांच नहीं करता है कि इसे समाप्त कर दिया गया है या नहीं। देखने के लिए किया जाए या नहीं यह बाधित कर दिया गया/बंद/समाप्त

myExecutor.execute(new Runnable() { 
public void run() { 
    while (!Thread.interrupted()) { 
    System.out.println("running"); 
    } 
} 
}); 
myExecutor.shutdownnow(); 

चूंकि यह धागा चेक: यह धागा, हालांकि, बंद हो जाएगा।

तो यदि आप एक धागा चाहते हैं जिसे आप बंद कर सकते हैं, तो आपको यह सुनिश्चित करना होगा कि यह जांचने के लिए जांच की गई है कि यह बाधित है या नहीं। यदि आप एक धागा चाहते हैं जिसे आप "बंद करें" और "पुनरारंभ" कर सकते हैं तो आप एक रननेबल बना सकते हैं जो पहले बताए गए नए कार्यों को ले सकता है।

आप एक चल रहे धागे को क्यों बंद नहीं कर सकते? खैर मैं वास्तव में झूठ बोला, आप "yourThread.stop()" पर कॉल कर सकते हैं, लेकिन यह एक बुरा विचार क्यों है? धागा एक सिंक्रनाइज़ (या अन्य महत्वपूर्ण खंड में हो सकता है, लेकिन जब हम इसे रोकते हैं तो कोड के अनुभाग) हम सिंक्रनाइज़ किए गए कुंजी शब्द द्वारा संरक्षित सेटों पर खुद को सीमित कर देंगे। सिंक ब्लॉक को उनके एंटीरिटी में निष्पादित किया जाना चाहिए और कुछ अन्य थ्रेड द्वारा एक्सेस किए जाने से पहले केवल एक थ्रेड द्वारा निष्पादित किया जाना चाहिए। यदि आप एक सिंच ब्लॉक के बीच में धागा रोकते हैं, तो सिंच ब्लॉक द्वारा रखी गई सुरक्षा को अमान्य कर दिया गया है और आपका प्रोग्राम अज्ञात स्थिति में जाएगा। डेवलपर्स चीजों को सिंक में रखने के लिए सिंक ब्लॉक में सामान डालते हैं, अगर आप थ्रेडइनस्टेंस.स्टॉप() का उपयोग करते हैं तो आप सिंक्रनाइज़ करने के अर्थ को नष्ट कर देते हैं, उस कोड का डेवलपर क्या करने की कोशिश कर रहा था और उस कोड के डेवलपर ने अपने सिंक्रनाइज़ किए गए ब्लॉक की अपेक्षा कैसे की पेश आ।

-1

मैं दावा से पूरी तरह से असहमत हूं कि आप "धागे को रोक नहीं सकते"। यह एक कांटेदार मुद्दे पर एक शॉर्ट्स दृश्य है। क्यूं कर?

नियमित रूप से बाधित-ध्वज की जांच करना वास्तव में "झंडे की जांच कब और कितनी बार" के कठिन निर्णय के साथ व्यस्त प्रतीक्षा के किसी अन्य रूप से कुछ और नहीं है। जवाब देने के लिए बहुत बदसूरत या असंभव हो सकता है। कक्षा धागे में "स्टॉप (थ्रोबल फेंकने योग्य)" विधि भी है, जिसे दुर्भाग्य से मैंने गलत तरीके से अस्वीकार कर दिया है। कोशिश करने के लिए विधि() को अपने शरीर के साथ एक प्रयास-अंत-कथन में दिया गया है: यह ठीक क्यों है कि किसी भी कथन (शरीर के अंदर से) स्टॉप के आमंत्रण के दौरान किसी भी चेक या अनचेक अपवाद को फेंक सकता है (नया MyRuntimeException ()) बाहर से नहीं हो सकता है? क्या यह वास्तव में बाहर से अप्रत्याशित है? फिर अप्रत्याशित RuntimeExceptions को पुनर्स्थापित करने के बारे में क्या है जिसे शायद ही कभी पकड़ा जाता है क्योंकि वे अक्सर अज्ञात होते हैं? अंत में, पकड़-खंडों को अपवाद से निपटना पड़ता है - चाहे वह अंदर से या बाहर से हो। और अंत में ब्लॉक साफ हो सकता है। मुझे आशा है कि लोग फिर से उस डिजाइन मुद्दे के बारे में सोचेंगे।

मुझे लगता है कि एक धागा मरने में सक्षम होना चाहिए (स्वयं को समाप्त करके) या मारने के लिए (तुरंत अपवाद के साथ समाप्त)।

-1

कभी कभी एक Thread शुरू किया गया था और यह एक नकारात्मक पक्ष यह गतिशील वर्ग जो Thread/currentThread नींद बहुत से संसाधित कर रहा है, जबकि Exception पकड़ (ते) बाधित अनदेखी भरी हुई है तो उसे एक बाधा पूरी तरह से बाहर निकलने के निष्पादन के लिए पर्याप्त नहीं हो सकता है।

उस मामले में, हम इन पाश आधारित बीच में आता है की आपूर्ति कर सकते हैं:

while(th.isAlive()){ 
    log.trace("Still processing Internally; Sending Interrupt;"); 
    th.interrupt(); 
    try { 
     Thread.currentThread().sleep(100); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 
0
You can start a thread like: 

    Thread thread=new Thread(new Runnable() { 
       @Override 
       public void run() { 
        try { 
         //Do you task 
        }catch (Exception ex){ 
         ex.printStackTrace();} 
       } 
      }); 
thread.start(); 

To stop a Thread: 

    thread.join();//it will kill you thread 

    //if you want to know whether your thread is alive or dead you can use 
System.out.println("Thread is "+thread.isAlive()); 

इसका यह पुन: प्रारंभ करने के बजाय किसी नए धागा बनाने के लिए सलाह दी जाती।

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