2008-09-18 15 views
28

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

मैं ऐसा कुछ कैसे कर सकता हूं?

पीएस: run() मेरे धागे की विधि में कोई लूप नहीं है, इसलिए ध्वज की जांच करना एक विकल्प नहीं है: 3 डी व्यू को अपडेट करने वाला धागा मूल रूप से केवल एक ही विधि को कॉल करता है जो निष्पादित करने में बहुत लंबा होता है। मैं इस विधि में किसी भी झंडे को जोड़ना नहीं चाहता हूं क्योंकि मुझे इसके कोड तक पहुंच नहीं है।

+0

आप हमें एपीआई का उपयोग कर रहे पर कुछ अधिक जानकारी दे सकते हैं? आप कहते हैं कि आप किसी तृतीय पक्ष लाइब्रेरी से कुछ विधि में कुछ सबमिट करते हैं, और इसमें काफी समय लगता है। क्या यह विधि आपके द्वारा पारित ऑब्जेक्ट को सीधे संशोधित करती है? या, क्या आप परिणामों के साथ कॉलबैक प्राप्त करते हैं? –

+0

क्या आपका आवेदन पूरा होने से पहले यह थ्रेड सामान्य रूप से समाप्त हो जाता है? यदि हां, तो इसका कारण क्या है? –

उत्तर

12

इंटरप्ट() को आज़माएं क्योंकि कुछ लोगों ने यह देखा है कि यह आपके धागे में कोई फर्क पड़ता है या नहीं।यदि नहीं, तो संसाधन को नष्ट करने या बंद करने का प्रयास करें जो थ्रेड स्टॉप करेगा। उस पर Thread.stop() फेंकने की कोशिश करने से थोड़ा बेहतर होने का मौका है।

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

boolean stopFlag = false; 
Object[] latestArgs = null; 

public void run() { 
    while (!stopFlag) { 
    if (latestArgs != null) { 
     Object[] args = latestArgs; 
     latestArgs = null; 
     perform3dUpdate(args); 
    } else { 
     Thread.sleep(500); 
    } 
    } 
} 

public void endThread() { 
    stopFlag = true; 
} 

public void updateSettings(Object[] args) { 
    latestArgs = args; 
} 
+0

यह मेरा समाधान होगा, धन्यवाद। नए समय के बजाय नए लूपिंग थ्रेड का उपयोग करना हर बार एक अच्छा विकल्प लगता है। मैं केवल एक मामूली संशोधन किए गए: मैं केवल perform3dUpdate() Jumar फोन करता है, तो latestArgs पिछले पास – jumar

+7

के बाद से संशोधित किया गया है खुशी है कि मैं मदद कर सकता है,! यह मेरा पहला स्टैक ओवरफ्लो पोस्ट था; मैंने विशेष रूप से इस विचार को पोस्ट करने के लिए साइन अप किया है। :) मैं endThread को बनाने चाहते हैं – skiphoppy

+0

दो संशोधनों: 1. आप वर्तमान वर्ग के लिए धागा वस्तु के लिए उपयोग किया है, तो मैं इसे जल्दी नींद() कॉल निरस्त करने के लिए बीच में होगा। 2. फिर, अगर आप धागा मिल सकता है, एक thread.join() endThread के अंत (कम से करते हैं) – nsayer

8

3 डी व्यू को अपडेट करने वाला थ्रेड समय-समय पर कुछ ध्वज (volatile boolean का उपयोग करें) को देखने के लिए देखना चाहिए कि इसे समाप्त करना चाहिए या नहीं। जब आप धागे को निरस्त करना चाहते हैं, तो बस ध्वज सेट करें। जब धागा अगला ध्वज की जांच करता है, तो इसे देखने के लिए उपयोग किए जाने वाले किसी भी लूप से इसे तोड़ना चाहिए और run विधि से वापस लौटना चाहिए।

यदि आप वास्तव में कोड का उपयोग नहीं कर सकते हैं तो थ्रेड चलने के लिए चल रहा है, तो थ्रेड को रोकने के लिए कोई सुरक्षित तरीका नहीं है। क्या आपका आवेदन पूरा होने से पहले यह थ्रेड सामान्य रूप से समाप्त हो जाता है? यदि हां, तो इसका कारण क्या है?

यदि यह कुछ लंबे समय तक चलता है, और आपको बस इसे समाप्त करना होगा, तो आप बहिष्कृत Thread.stop() विधि का उपयोग करने पर विचार कर सकते हैं। हालांकि, यह एक अच्छे कारण के लिए बहिष्कृत किया गया था। अगर उस ऑपरेशन को कुछ ऑपरेशन के बीच में रोक दिया जाता है जो किसी असंगत स्थिति में कुछ छोड़ देता है या कुछ संसाधन ठीक से साफ नहीं होता है, तो आप परेशानी में पड़ सकते हैं। यहां documentation:

यह विधि स्वाभाविक रूप से असुरक्षित है। यह पर नज़र रखता है कि यह (अनियंत्रित ThreadDeath अपवाद ढेर अप प्रचार का एक प्राकृतिक परिणाम के रूप) बंद कर दिया गया के सभी अनलॉक करने के लिए कारण बनता है Thread.stop साथ एक धागा रोक। यदि पहले से इन मॉनीटरों द्वारा संरक्षित एक असंगत स्थिति में थे, क्षतिग्रस्त वस्तुएं अन्य धागे पर दिखाई देती हैं, संभावित रूप से परिणामस्वरूप मनमाने ढंग से व्यवहार में। स्टॉप के कई उपयोगों को कोड द्वारा प्रतिस्थापित किया जाना चाहिए बस कुछ चर को में संशोधित करता है इंगित करता है कि लक्ष्य धागा चलना बंद कर देना चाहिए। लक्ष्य धागा नियमित रूप से इस चर को जांचें, और में क्रमिक रूप से फ़्रेम विधि से वापस आते हैं यदि परिवर्तनीय इंगित करता है कि यह चलना बंद करना है। यदि लक्ष्य धागा लंबे अवधि (एक शर्त चर पर, उदाहरण के लिए) के लिए इंतजार कर रहा है, तो इंटरप्ट विधि प्रतीक्षा को बाधित करने के लिए उपयोग की जानी चाहिए। अधिक जानकारी के लिए, Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

+0

3 डी व्यू को अपडेट करने वाला ट्रेड मूल रूप से केवल एक ही विधि को कॉल करता है जो निष्पादित करने में बहुत लंबा होता है। मैं इस विधि में कोई झंडा नहीं जोड़ सकता क्योंकि मेरे पास इसके कोड तक पहुंच नहीं है। तो इस समाधान का उपयोग यहां नहीं किया जा सकता है। – jumar

+0

डेव एल द्वारा प्रस्तावित समाधान सही है। यदि आपके पास तीसरे पक्ष के कोड के स्रोत तक कोई पहुंच नहीं है तो शायद आपके द्वारा छोड़ा गया एकमात्र सहारा बाइटकोड मैनिपुलेशन है। एएसएम (http://asm.objectweb.org/) जैसी लाइब्रेरी का उपयोग करके आप रनटाइम पर कक्षा को संशोधित कर सकते हैं और अपना कोड "इंजेक्ट" कर सकते हैं। –

-1

हो सकता है कि यह आपकी मदद कर सकते हैं: How can we kill a running thread in Java?

आप किसी बाहरी वर्ग चर की स्थापना करके एक विशेष धागा मार सकते हैं।

Class Outer 
{  
    public static flag=true; 
    Outer() 
    { 
     new Test().start(); 
    } 
    class Test extends Thread 
    {    
     public void run() 
     { 
     while(Outer.flag) 
     { 
      //do your work here 
     } 
     } 
    } 
    } 

यदि आप ऊपर धागा बंद करना चाहते हैं, false को झंडा चर सेट। थ्रेड को मारने का दूसरा तरीका सिर्फ इसे थ्रेड ग्रुप में पंजीकृत कर रहा है, फिर destroy() पर कॉल करें। इस तरह समूह के रूप में उन्हें बनाकर या समूह के साथ पंजीकरण करके समान धागे को मारने के लिए भी इसका उपयोग किया जा सकता है।

+4

यदि आप चाहते हैं कि लोग आपको गंभीरता से ले जाएं, तो "यू" और "यूआर" का उपयोग करना बंद करें। उस पूरे अतिरिक्त 2 अक्षरों को टाइप करने के लिए समय निकालें - यह आपको लंबे समय तक देरी नहीं करेगा। –

1

तरह से मैं अतीत में कुछ इस तरह लागू किया है मेरी Runnable उपवर्ग जो एक उदाहरण चर सच करने के लिए कहा जाता है should_shutdown सेट में एक shutdown() विधि लागू करने के लिए है। run() विधि आमतौर पर लूप में कुछ करता है, और समय-समय पर should_shutdown जांचता है और जब यह सत्य होता है, रिटर्न करता है, या do_shutdown() पर कॉल करता है और फिर देता है।

आपको वर्तमान कार्यकर्ता थ्रेड के लिए संदर्भ रखना चाहिए, और जब उपयोगकर्ता कोई मान बदलता है, तो वर्तमान थ्रेड पर shutdown() पर कॉल करें, और इसे बंद करने के लिए प्रतीक्षा करें। फिर आप एक नया धागा लॉन्च कर सकते हैं।

मैं Thread.stop का उपयोग करने की अनुशंसा नहीं करता क्योंकि यह पिछली बार मैंने चेक किया था।

संपादित करें:

कैसे अपने कार्यकर्ता धागा सिर्फ एक और तरीका है जो चलाने के लिए कुछ समय लगता है कहता है, तो ऊपर लागू नहीं होता है के बारे में अपनी टिप्पणी पढ़ें। इस मामले में, आपके केवल वास्तविक विकल्प interrupt() पर कॉल करने का प्रयास करें और देखें कि इसका कोई प्रभाव है या नहीं। यदि नहीं, तो किसी भी तरह से मैन्युअल रूप से फ़ंक्शन को आपके कार्यकर्ता थ्रेड को तोड़ने के लिए कॉल करने पर विचार करें। उदाहरण के लिए, ऐसा लगता है कि यह कुछ जटिल प्रतिपादन कर रहा है, इसलिए शायद कैनवास को नष्ट कर दें और इसे अपवाद फेंक दें। यह एक अच्छा समाधान नहीं है, लेकिन जहाँ तक मैं बता सकता हूँ, यह केवल इस तरह suituations में एक धागा बंद करने के लिए रास्ता है।

1

run() विधि पूर्ण होने के बाद एक थ्रेड बाहर निकल जाएगा, इसलिए आपको कुछ चेक की आवश्यकता है जो इसे विधि को पूरा कर देगा।

आप थ्रेड को बाधित कर सकते हैं, और उसके बाद कुछ चेक है जो समय-समय पर isInterrupted() की जांच करेगा और run() विधि से बाहर निकल जाएगा।

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

static boolean shouldExit = false; 
Thread t = new Thread(new Runnable() { 
    public void run() { 
     while (!shouldExit) { 
      // do stuff 
     } 
    } 
}).start(); 
1

दुर्भाग्य से एक धागे की हत्या संसाधनों का उपयोग कर की संभावनाओं कि ताले द्वारा सिंक्रनाइज़ किया जा सकता है की वजह से स्वाभाविक रूप से असुरक्षित है अगर धागा आप वर्तमान में मारने के एक ताला कार्यक्रम गतिरोध में जा रहा में परिणाम सकता है (स्थिर है एक संसाधन को पकड़ने का प्रयास करें जिसे प्राप्त नहीं किया जा सकता है)। आपको मैन्युअल रूप से जांचना होगा कि क्या उस थ्रेड से उसे मारने की आवश्यकता है जिसे आप रोकना चाहते हैं। अस्थिरता पहले से संग्रहीत किए गए किसी चीज़ की बजाय चर के वास्तविक मूल्य की जांच सुनिश्चित करेगी। बाहर निकलने धागे पर एक तरफ ध्यान दें Thread.join पर आप जब तक प्रतीक्षा मर धागा वास्तव में इससे पहले कि आप नहीं बल्कि हर समय जाँच से कुछ भी कर चला गया है सुनिश्चित करने के लिए।

4

इसके बजाय अपने खुद के बूलियन ध्वज रोलिंग, क्यों नहीं बस जावा धागे में पहले से ही धागा बाधा तंत्र का उपयोग की? कैसे आंतरिक कोड आप बदल नहीं सकते में लागू किया गया के आधार पर आप भी इसके निष्पादन का हिस्सा निरस्त करने के लिए सक्षम हो सकता है।

बाहरी धागा:

if(oldThread.isRunning()) 
{ 
    oldThread.interrupt(); 
    // Be careful if you're doing this in response to a user 
    // action on the Event Thread 
    // Blocking the Event Dispatch Thread in Java is BAD BAD BAD 
    oldThread.join(); 
} 

oldThread = new Thread(someRunnable); 
oldThread.start(); 

इनर Runnable/थ्रेड:

public void run() 
{ 
    // If this is all you're doing, interrupts and boolean flags may not work 
    callExternalMethod(args); 
} 

public void run() 
{ 
    while(!Thread.currentThread().isInterrupted) 
    { 
     // If you have multiple steps in here, check interrupted peridically and 
     // abort the while loop cleanly 
    } 
} 
+0

आपके प्रश्न का उत्तर करने के लिए, ऐसा इसलिए है क्योंकि Thread.intrerrupt() कुछ आईओ या संगामिति आपरेशनों के दौरान अपवाद फेंक कर दुष्प्रभाव हो सकते हैं। कभी-कभी यह वही है जो आप चाहते हैं, लेकिन हमेशा नहीं। –

0

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

चूंकि वह विकल्प आपके लिए उपलब्ध नहीं है, इसलिए एकमात्र अन्य विकल्प चल रही प्रक्रिया को छोड़ने के लिए मजबूर करना है। यह Thread.stop() फोन करके संभव हुआ करता था, लेकिन यह है कि विधि स्थायी रूप से निम्न कारण (कारणों javadocs से नकल) के लिए पदावनत किया गया है:

इस विधि स्वाभाविक असुरक्षित है। Thread.stop के साथ थ्रेड को रोकने से यह उन सभी मॉनीटर को अनलॉक कर देता है जो इसे लॉक कर चुके हैं (अनचेक थ्रेडडिथ अपवाद के प्राकृतिक परिणाम के रूप में स्टैक को प्रसारित करते हैं)। यदि इन मॉनीटरों द्वारा पहले संरक्षित वस्तुओं में से कोई भी एक असंगत स्थिति में था, तो क्षतिग्रस्त वस्तुएं अन्य धागे के लिए दृश्यमान हो जाती हैं, संभावित रूप से मनमाना व्यवहार में परिणामस्वरूप।

इस विषय पर अधिक जानकारी here मिल सकती है।

एक पूर्ण यकीन है कि जिस तरह से आप अपने अनुरोध को पूरा कर सकते हैं (हालांकि यह यह करने के लिए एक बहुत ही कुशल तरीका नहीं है) Runtime.exec() माध्यम से एक नया जावा प्रक्रिया शुरू है और फिर उस प्रक्रिया Process.destroy() के माध्यम से आवश्यक के रूप में रोकने के लिए है। हालांकि, इस तरह की प्रक्रियाओं के बीच राज्य साझा करना बिल्कुल मामूली नहीं है।

0

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

क्षमा करें, अपने प्रश्न को फिर से पढ़ने के बाद, न तो यह और न ही किसी अन्य 'चेक चर' सुझाव आपकी समस्या का समाधान करेंगे।

3

क्या यह पूछने की तरह थोड़ा नहीं है "थ्रेड.स्टॉप() के अलावा कोई विधि उपलब्ध नहीं होने पर मैं थ्रेड को कैसे रोक सकता हूं?"

जाहिर है, केवल वैध उत्तर Thread.stop() है। इसकी बदसूरत, कुछ परिस्थितियों में चीजों को तोड़ सकती है, स्मृति/संसाधन लीक का कारण बन सकती है, और टीएलईजेडी (असाधारण जावा डेवलपर्स लीग) द्वारा फेंक दी गई है, हालांकि यह अभी भी कुछ मामलों में उपयोगी हो सकती है। अगर तीसरे पक्ष के कोड में कुछ करीबी विधि उपलब्ध नहीं है तो वास्तव में कोई अन्य विधि नहीं है।

ओटीओएच, कभी-कभी पिछवाड़े बंद तरीके भी होते हैं। हां, एक अंतर्निहित धारा को बंद करना जो इसके साथ काम कर रहा है, या कुछ अन्य संसाधन जो इसे अपना काम करने की ज़रूरत है। यह Thread.stop() को कॉल करने और इसे थ्रेडडिथ अपवाद का अनुभव करने की तुलना में शायद ही कभी बेहतर है।

1

आपको लगता है कि स्क्रीन को प्रस्तुत करने वाले थ्रेड पर कोई नियंत्रण नहीं है लेकिन आप स्पिनर घटक पर नियंत्रण रखते हैं। धागा स्क्रीन को प्रतिपादित करते समय मैं स्पिनर को अक्षम कर दूंगा। इस तरह उपयोगकर्ता को कम से कम उनके कार्यों से संबंधित कुछ प्रतिक्रिया होती है।

1

मेरा सुझाव है कि आप सिर्फ इंतजार का उपयोग करके एकाधिक धागे को रोकने और इतने सूचित करें कि उपयोगकर्ता मूल्य कई बार परिवर्तित करता है यह केवल एक बार थ्रेड चलेंगे। यदि उपयोगकर्ता 10 बार मान बदलते हैं तो यह थ्रेड को पहले बदलाव पर बंद कर देगा और फिर थ्रेड से पहले किए गए किसी भी बदलाव को सभी को एक अधिसूचना में "लुढ़का" मिल जाएगा। यह थ्रेड को नहीं रोकेगा लेकिन आपके विवरण के आधार पर ऐसा करने के कोई अच्छे तरीके नहीं हैं।

1

समाधान जो बूलियन क्षेत्र के उपयोग के उद्देश्य से सही दिशा हैं। लेकिन क्षेत्र अस्थिर होना चाहिए। जावा भाषा युक्ति says:

"उदाहरण के लिए, निम्नलिखित (टूट) कोड टुकड़ा में, मान लेते हैं कि this.done गैर अस्थिर बूलियन क्षेत्र है:

while (!this.done) 
    Thread.sleep(1000); 

संकलक है इस क्षेत्र को पढ़ने के लिए स्वतंत्र है। सिर्फ एक बार, और लूप के प्रत्येक निष्पादन में कैश किए गए मान का पुन: उपयोग करें। इसका मतलब यह होगा कि लूप कभी समाप्त नहीं होगा, भले ही कोई अन्य धागा इस.done के मान को बदल देगा। "

जहाँ तक मुझे java.lang.Thread की interrupt() और interrupted() विधियों का उपयोग करने "Java Concurrency in Pratice" प्रयोजनों याद के रूप में।

1

इस प्रश्न का स्वीकृत उत्तर आपको पृष्ठभूमि थ्रेड में बैच कार्य सबमिट करने की अनुमति देता है। यह है कि के लिए एक बेहतर पैटर्न हो सकता है:

public abstract class dispatcher<T> extends Thread { 

    protected abstract void processItem(T work); 

    private List<T> workItems = new ArrayList<T>(); 
    private boolean stopping = false; 
    public void submit(T work) { 
    synchronized(workItems) { 
     workItems.add(work); 
     workItems.notify(); 
    } 
    } 
    public void exit() { 
    stopping = true; 
    synchronized(workItems) { 
     workItems.notifyAll(); 
    } 
    this.join(); 
    } 
    public void run() { 
    while(!stopping) { 
     T work; 
     synchronized(workItems) { 
     if (workItems.empty()) { 
      workItems.wait(); 
      continue; 
     } 
     work = workItems.remove(0); 
     } 
     this.processItem(work); 
    } 
    } 
} 

इस वर्ग का उपयोग करने के लिए, यह विस्तार, टी के लिए एक प्रकार और processItem के एक कार्यान्वयन() प्रदान करते हैं। फिर बस एक बनाएं और उस पर कॉल शुरू करें()।

आप एक abortPending विधि जोड़ने पर विचार हो सकता है:

public void abortPending() { 
    synchronized(workItems) { 
    workItems.clear(); 
    } 
} 
उन मामलों में जहाँ उपयोगकर्ता प्रतिपादन इंजन के आगे छोड़ दिया गया है के लिए

और आप काम है कि अब तक तय किया गया है फेंक करना चाहते हैं।

0

सही उत्तर धागे का उपयोग नहीं करना है।

आप निष्पादकों का उपयोग किया, पैकेज देखना चाहिए: java.util.concurrent

+5

मैं माफी चाहता लेकिन कह रही है कि निष्पादकों समझा क्यों है बिना धागे से बेहतर हैं रहा हूँ, यह उपयोगी नहीं है। तो मैं आपसे यह पूछता हूं: किस तरह से निष्पादक धागे से बेहतर तरीके से हैं? क्या वे हमेशा * बेहतर होते हैं या ऐसे समय होते हैं जब धागे को प्राथमिकता दी जाती है? –

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