2012-02-29 9 views
7

रोकना मेरे लिए यह एक मामला हो सकता है जो मैंने पढ़ा है, लेकिन जावा में धागे को मारने के लिए सभी उदाहरण यह इंगित करते हैं कि आपको खुद को मारने के लिए धागे को सिग्नल करना है; आप बिना किसी गंभीर जोखिम के बाहर से इसे मार नहीं सकते हैं। समस्या यह है कि, "विनम्रतापूर्वक" मरने के लिए एक धागे से पूछने के सभी उदाहरणों में कुछ प्रकार के लूपिंग होते हैं, इसलिए आपको बस इतना करना है कि प्रत्येक पुनरावृत्ति पर ध्वज देखें।एक गैर-लूपिंग जावा थ्रेड

तो, मुझे जो मिला है वह एक थ्रेड है जो कुछ ऐसा करता है जो कुछ समय लेता है (SQL क्वेरी की एक श्रृंखला)। मेरे लिए निश्चित रूप से प्रत्येक चरण के बाद जांच करना संभव है, लेकिन वे एक लूप में नहीं हैं और एक बहुत ही सुरुचिपूर्ण तरीका नहीं है जिसे मैं इसके बारे में जानने के बारे में जानता हूं। यहाँ मैं क्या कर रहा हूं, इसका एक उदाहरण:

new Thread(new Runnable(){ 
    public void run(){ 
     //query 1 
     Connection conn = db.getConnection(); 
     Statement s = conn.createStatement(); 
     ResultSet rs = s.executeQuery("SELECT ..."); 
     while(rs.next()){ 
      //do stuff 
     } 

     //query 2 
     rs = s.executeQuery("SELECT ..."); 
     while(rs.next()){ 
      //do stuff 
     } 

     //query 3 
     rs = s.executeQuery("SELECT ..."); 
     while(rs.next()){ 
      //do stuff 
     } 
    } 
}).start(); 

यह एक उदाहरण है, मैं गुमनाम इनर क्लासों का उपयोग नहीं करते लेकिन यह दिखाता है कि मेरी रन() विधि सुंदर ढंग से खुद को नहीं रोक सकता। फ़्यूथरमोर, यहां तक ​​कि मैं प्रत्येक चरण के बाद भी जांच करता हूं, यदि किसी विशेष क्वेरी को चलाने में बहुत लंबा समय लगता है, तो यह कोड पूरा होने के बाद तक यह कोड रुकने में सक्षम नहीं होगा।

यह कोड एक जीयूआई अनुप्रयोग के लिए है, और मैं वास्तव में Thread.stop() का उपयोग किए बिना थ्रेड को मारने का एक अच्छा तरीका खोजना चाहता हूं।

EDIT - यशवित का जवाब एक बड़ी मदद थी, क्योंकि मुझे पता नहीं था कि Statement.cancel() मौजूद था। यदि आप उत्सुक हैं, तो मेरी विशेष समस्या का उत्तर एक अधिक सारणित डेटाबेस एक्सेस क्लास बनाना था। कक्षा को चलने के दौरान क्वेरी और लूप निष्पादित करने के लिए एक बच्चे धागा बनाना था, अगर मौजूदा धागा (बच्चा नहीं) बाधित हो तो प्रत्येक पुनरावृत्ति पर जांच कर रहा था। यदि यह बाधित हो जाता है, तो यह सिर्फ स्टेटमेंट.cancel() को कॉल करता है और बाल धागा अपवाद फेंक देगा और मर जाएगा। सभी जेडीबीसी ड्राइवर Statement.cancel() का समर्थन नहीं करते हैं, लेकिन ओरेकल 11 जी करता है।

+0

संभव डुप्लिकेट [जावा में तेज और साफ तरीके से धागे को कैसे रोकें?] (Http://stackoverflow.com/questions/94011/how-to-abort-a-thread-in-a-fast -और-क्लीन-वे-इन-जावा) –

+0

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

उत्तर

4

पता लगाएं कि इसमें कुछ समय लगता है, और इसे रद्द करें। बात यह है कि सबसे अधिक समय लेता है rs.next() छोरों हैं, तो आप कर सकते हैं:

while(rs.next()){ 
    if (myVolatileBooleanSaysToStop) { 
     return; // or whatever 
    } 
    //do stuff 
} 

बात यह है कि कुछ समय लगता है बयान, और अपने JDBC- चालक/सर्वर समर्थन Statement.cancel कर रहे हैं, तो आप अपने Statement प्रकाशित कर सकते हैं एक दूसरे थ्रेड के लिए जो उपयुक्त के रूप में Statement.cancel पर कॉल करने के लिए ज़िम्मेदार है। मुझे यकीन नहीं है, लेकिन मुझे लगता है कि ड्राइवर से SQLException का परिणाम होगा, जिसे आप किसी भी तरह रद्दीकरण से आने के रूप में पहचान सकते हैं, और तदनुसार संभाल सकते हैं।

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

+0

कई डेटाबेस ड्राइवर स्टेटमेंट और परिणामसेट ऑब्जेक्ट्स के लिए थ्रेड सुरक्षित नहीं होंगे, भले ही जेडीबीसी स्पेक कहता है कि वे होना चाहिए। –

+0

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

+0

@monitorjbl कुरूपता के बारे में, वास्तव में एक विकल्प नहीं है। यही कारण है कि मैंने कोड को दोबारा करने का सुझाव दिया - यह कुरूपता को समेकित करता है। चूंकि क्वेरी में लंबे समय तक लगने के लिए, यदि आप ड्राइवर के कारण इसे रद्द नहीं कर सकते हैं, तो आप अपने ऐप से बहुत कुछ नहीं कर सकते हैं। – yshavit

0

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

1

आप अपने खुद के thread.kill() खरोंच से तंत्र को लागू नहीं करना चाहते हैं, तो आप, मौजूदा एपीआई का उपयोग एक ThreadPoolExecutor के भीतर अपने धागा निर्माण प्रबंधित करें, और Future.cancel() का उपयोग चल रहे धागा को मारने के लिए कर सकते हैं:

ThreadPoolExecutor threadPoolExecutor = Executors.newSingleThreadExecutor(); 
Runnable longRunningTask = new Runnable(); 

// submit task to threadpool: 
Future longRunningTaskFuture = threadPoolExecutor.submit(longRunningTask); 

... ... 
// At some point in the future, if you want to kill the task: 
longRunningTaskFuture.cancel(true); 
... ... 

रद्द करें विधि आपके कार्य चल रहे राज्य के आधार पर अलग-अलग व्यवहार करेगी, अधिक जानकारी के लिए API देखें।

0

एक धागा ग्राहक (यानी कोड धागे की चल बाहर) बीच में करने के लिए:

threadInstance.interrupt(); 

को देखने के लिए यह जांचने के लिए धागा अपने कोड पर चल रहा है बाधित कर दिया गया है

Thread.currentThread().isInterrupted() 

एक और विकल्प है कोशिश करना और सोना:

Thread.currentThread().sleep(1) 

सोने के बारे में क्या अच्छा है यह फेंक देगा n अपवाद अगर धागा बाधित हो गया है (यानी इंटरप्टेड एक्सेप्शन) यही कारण है कि उन अपवादों को अनदेखा करना महत्वपूर्ण नहीं है।

आप थ्रेड.currentThread() का उपयोग करते हुए अपने समय के लूप के अंदर चेक जोड़ सकते हैं। अंतर्निहित() है या आप विवरणों के बीच नींद (1) की जांच कर सकते हैं। मैं लूप में सो नहीं पाऊंगा क्योंकि यह वास्तव में आपके कोड को धीमा कर देगा। यह वह जगह है जहां एक संकर दृष्टिकोण सबसे अच्छा हो सकता है:

if(Thread.currentThread().isInterrupted()) throw new InterruptedException(); 

फिर आप इसे अपने रन() विधि की सीमाओं पर रोकें और रोकें।

बिंदु आपको यह देखने के लिए समय-समय पर जांच करनी है कि बाहरी क्लाइंट ने आपको शट डाउन करने का अनुरोध किया है या नहीं। यदि आपके पास धागे में 6 कथन थे। उन बयानों के बीच चेक डालने से आपके धागे को छोड़ने की अनुमति मिल जाएगी।

public run() { 
    try { 
     doSomething(); 
     if(Thread.currentInstance().isInterrupted()) throw new InterruptException(); 
     doNextSomething(); 
     if(Thread.currentInstance().isInterrupted()) throw new InterruptException(); 
     doSomeMoreThings(); 
     if(Thread.currentInstance().isInterrupted()) throw new InterruptException(); 
     doYetMoreThings(); 
    } catch(InterruptedException e) { 
     System.out.println("Duff man going down."); 
    } 
} 

ऐसा करने के बीच वास्तव में कोई अंतर नहीं है और एक लूप में एक चेक डालने में कोई अंतर नहीं है।

0

यदि आप थ्रेड को बाधित नहीं करना चाहते हैं तो एकमात्र अन्य विकल्प किसी भी तरह से चलने वाली क्वेरी को मार/रद्द करना है। यदि आप क्वेरी एसिंक शुरू कर सकते हैं तो आप केवल तब तक प्रतीक्षा कर सकते हैं जब तक कि परिणाम तैयार न हों या आपको मरने के लिए संकेत मिले, लेकिन आप cannot call jdbc async

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