मेरे आवेदन में मेरे पास कुछ मूल कोड पर एक रैपर है, जिसे जेएनआई पुल के माध्यम से बुलाया जाता है। इस देशी कोड को अलग थ्रेड (समांतर प्रसंस्करण) में निष्पादित करने की आवश्यकता है। हालांकि समस्या यह है कि कोड कभी-कभी "लटकता" है, इसलिए थ्रेड को "बलपूर्वक" समाप्त किया जाना चाहिए। दुर्भाग्यवश मुझे ऐसा करने के लिए कोई "नाज़ुक" विधि नहीं मिली है: सामान्य सलाह है कि कोड को थ्रेड में कोड को सुन्दर तरीके से बाहर निकलने के लिए बताना है, लेकिन मैं इसे इस मूल कोड (जो ऊपर तीसरा पक्ष कोड है) के साथ नहीं कर सकता।एक धागा को समाप्त करें जो मूल कोड चला रहा है
मैं काम प्रस्तुत करने के लिए जावा समवर्ती एपीआई का उपयोग:
Future<Integer> processFuture = taskExecutor.submit(callable);
try {
result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
// How to kill the thread here?
throw new ExecutionTimeoutException("Execution timed out (max " + this.executionTimeout/60 + "min)");
}
catch (...) {
... exception handling for other cases
}
Future#cancel()
केवल धागा को बाधित करता है, लेकिन यह इसे समाप्त नहीं होंगे।
class DestroyableCallable implements Callable<Integer> {
private Thread workerThread;
@Override
public Integer call() {
workerThread = Thread.currentThread();
return Integer.valueOf(JniBridge.process(...));
}
public void stopWorkerThread() {
if (workerThread != null) {
workerThread.stop();
}
}
}
DestroyableCallable callable = new DestroyableCallable();
Future<Integer> processFuture = taskExecutor.submit(callable);
try {
result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
processFuture.cancel(true);
// Dirty:
callable.stopWorkerThread();
ThreadPoolTaskExecutor threadPoolTaskExecutor = (ThreadPoolTaskExecutor) taskExecutor;
logger.debug("poolSize: " + threadPoolTaskExecutor.getPoolSize() + ", maxPoolSize:"
+ threadPoolTaskExecutor.getMaxPoolSize() + ", activeCount:"
+ threadPoolTaskExecutor.getActiveCount());
}
throw new ...;
}
catch (...) {
... exception handling for other cases
}
प्रश्न/इस कोड के साथ समस्याओं:
- यह सामान्य रूप में ऐसा करने का अधिकार रास्ता नहीं है तो मैं निम्नलिखित चाल का इस्तेमाल किया? कोई और अधिक सुरुचिपूर्ण विकल्प?
activeCount
कार्य निष्पादक पर कम नहीं है, इसलिए कार्य निष्पादक अभी भी "सोचता है कि" कि धागा चल रहा है- मैं
stopWorkerThread()
विधि के लिएworkerThread != null
जांच जोड़ने के लिए किया था, के रूप में इस चर निकलाnull
कुछ मामले पर किया जाना है। मुझे समझ में नहीं कर सकते इन मामलों रहे हैं क्या ...
नोट्स:
- मूल निवासी कोड फ़ाइल वर्णनकर्ता (सॉकेट) का उपभोग नहीं करता है। सबकुछ इसे डेटा के ब्लॉक के रूप में पास कर दिया जाता है और उसी तरह लौटा दिया जाता है।
- मूल कोड सीपीयू-गहन है। हालांकि यह समाप्त होने की गारंटी देता है, लेकिन इसमें काफी समय लग सकता है।
बाउंटी संपादित: दृष्टिकोण/सुझाव फिर से मूल कोड स्पष्ट है, अपने उत्तर में यह प्रस्ताव नहीं है। मुझे शुद्ध-जावा समाधान/वर्कअराउंड चाहिए।
धन्यवाद उचित नोटिस। आपकी पोस्ट के लिए एक छोटी टिप्पणी: चूंकि लॉन्च थ्रेड मूल कोड निष्पादित कर रहा है, वहां कोई ताले नहीं हैं (जब तक आप इसे जेएनआई के माध्यम से स्पष्ट रूप से कोड नहीं करते) जिन्हें जावा-पार्ट के साथ साझा किया जाता है। तो एकमात्र जोखिम भरा संसाधन फ़ाइल डिस्क्रिप्टर खोला गया है (जो मेरे लिए मामला नहीं है, क्योंकि सभी आवश्यक डेटा ब्लॉब के रूप में पारित किया जाता है और स्ट्रिंग के रूप में वापस ले लिया जाता है)। एकमात्र समस्या यह है कि 'थ्रेडपूल टास्क एक्स्सेलर' को कैसे बताना है कि थ्रेड वास्तव में मर गया था? मैंने कोड को देखा है: इसे वास्तव में इस मामले को कैप्चर करना चाहिए। –
कोई ताले नहीं - ठीक है, हो सकता है। लेकिन देशी कोड में मेमोरी लीक के बारे में क्या? क्या आप सुनिश्चित कर सकते हैं कि देशी lib को असामान्य समाप्ति प्रक्रिया को गहन तरीके से संसाधित करने के लिए पर्याप्त सुरक्षित और कोडित किया गया था? क्या यह असामान्य एक सहित सभी निकास पथों पर आवंटित स्मृति जारी करता है? मूल कोड में लीक, स्मृति के साथ आप क्या करेंगे?कुछ ओएस-स्तरीय संसाधनों के बारे में वही सवाल - क्या होगा यदि मूल lib कर्नेल-स्तर लॉक आवंटित करता है? कई अतिरिक्त धागे शुरू करता है? – BegemoT
मैं ढेर पर मेमोरी लीक से संबंधित हूं (जैसा कि [धागे एक ही ढेर साझा करते हैं] (http://stackoverflow.com/questions/1665419))। मैं एक विशेषज्ञ नहीं हूं, लेकिन मुझे नहीं लगता कि उपयोगकर्ता थ्रेड को कर्नेल मोड में बाधित किया जा सकता है, अन्यथा धागे को मारने से नुकसान होगा। डिस्क पर कुछ लिखते समय थ्रेड मारा गया था, तो फाइल सिस्टम। तो अप्रकाशित कर्नेल-स्तर ताले बहुत दुखी होंगे। बाकी के लिए मैं आपकी स्थिति का पूर्ण समर्थन करता हूं: प्रक्रिया अधिक सुरक्षित है। जेएनआई पुल पर अधिक स्टैंडअलोन प्रक्रिया से मेरे द्वारा बनाया गया था, इसलिए इसे वापस करने का कोई प्रयास नहीं है। –