2017-01-17 8 views
5

क्यों नहीं रोक सकता है क्यों मेरा धागा रोका नहीं जा सकता ???थ्रेड

class Threadz { 

    class runP implements Runnable { 
     int num; 
     private volatile boolean exit = false; 
     Thread t; 
     public runP() { 
      t = new Thread(this, "T1"); 
      t.start(); 
     } 

     @Override 
     public void run() { 
      while(!exit) { 
       System.out.println(t.currentThread().getName()+": "+num); 
       num++; 
       try { 
        t.sleep(200); 
       } catch(InterruptedException e) {} 
      } 
     } 
     public void stop() { 
      exit = true; 
     } 
    } 

    public static void main(String[] a) { 
     runP rp = new Threadz().new runP(); 
     if(rp.num == 1) {rp.stop();} 
    } 

} 

यदि मैं rp.num == 0 का उपयोग करता हूं, तो थ्रेड तुरंत बंद किया जा सकता है। लेकिन, जब मैंने rp.num == x बदल दिया (x 0 से अधिक संख्या है) धागा रुक नहीं सकता है? कृपया मुझे इस बात को हल करने में मदद करें ... किसी भी मदद के लिए धन्यवाद।

+2

मुझे लगता है कि 'runP आरपी कुछ ऐसा दिखाई देगा = नया थ्रेडज़()। नया रनपी(); 'थ्रेड बना रहा है और शुरू कर रहा है। हालांकि, 'अगर (rp.num == 1) {rp.stop();}' उस _might_ के ठीक बाद उस अन्य थ्रेड को वास्तव में चलाना शुरू करने से ठीक पहले निष्पादित किया गया था, इसलिए 'num' अभी भी 0 है। इसके अतिरिक्त थ्रेड पहले से ही हो सकता है इस प्रकार 'rp.num == 1' की जांच करने के लिए कई बार चलाएं _very_ नाजुक है और शायद अधिकतर विफल नहीं होगा। – Thomas

+0

कृपया अपने थ्रेड को रोकने के लिए 'rp.num == 1' के बजाय 'rp.num = 1 1' का उपयोग करने पर विचार करें ताकि आप यह सुनिश्चित कर सकें कि आप अपनी स्टॉप स्थिति को गलती से नहीं छोड़ते हैं। – Quota

+0

वास्तव में इस दृष्टिकोण को रखने के लिए आपको AtomicBoolean का उपयोग करने की आवश्यकता है। इसके अलावा आपको == को हिट करने के लिए दोनों धागे के बीच एक प्रीफेक्ट समय की आवश्यकता है। आप – efekctive

उत्तर

3

क्योंकि इस कोड धागे की विधि रन() में मार डाला नहीं है:

runP rp = new Threadz().new runP(); 
    if (rp.num == 1) { 
     rp.stop(); 
    } 

यह 0 के साथ काम करता के रूप में पूर्णांक का डिफ़ॉल्ट मान 0. है लेकिन यह आवश्यक रूप से सभी सज़ाएँ में सच नहीं है

: if (rp.num == 0)

runP धागे की रन विधि में बंद हालत में स्थानांतरित करें: runP का धागा चलाने के लिए और जांच से पहले num को बढ़ा सकता है के रूप में आवेदन की

+0

के साथ बेहतर हैं .. ठीक है .. मैं कोशिश कर सकता हूं लेकिन इस विकल्प के साथ समाप्त हो सकता है ... धन्यवाद ब्रो – BeginnerToJava

+0

बीटीडब्ल्यू अगर मेरे पास 2 थ्रेड हैं, तो 1 थ्रेड से दूसरे को कैसे पास किया जाए? आप मुझे बताएंगे कि कैसे? – BeginnerToJava

+0

आपका स्वागत है :) परिवर्तनीय को पास करने की आवश्यकता नहीं है, बस इसे अपने धागे के बीच साझा करें। आप एक एटमिकइंटर का उपयोग कर सकते हैं जिसे आप रनपी थ्रेड्स के बीच साझा करते हैं और एटमिकइंटर को runP के कन्स्ट्रक्टर में प्रदान करते हैं। यह अच्छा होना चाहिए। – davidxxx

0

मुझे यकीन है कि यदि आप प्रोग्राम को कई बार चलाते हैं, तो यह एक ऐसा मामला होगा जब कार्यक्रम वास्तव में बंद हो जाता है।

कारण आपकी run() विधि में

if(rp.num == 1) {rp.stop();} 
num++ से पहले

क्रियान्वित मूल्य में परिवर्तन की बहुत अधिक संभावना है बार जब आप प्रोग्राम चलाने पर है।

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

उदहारण के लिए: यकीन है कि यह होता है लगातार हालत की जांच करने वाली बनाने के लिए

एक ही रास्ता

public static void main(String[] a) { 
    runP rp = new Threadz().new runP(); 

    while(true){ 
     if(rp.num == 1) { 
     rp.stop(); 
     break; 
     } 
    } 
} 
0

धागा रन विधि को निष्पादित करने से पहले निष्पादित किया जा रहा है।

if(rp.num == 1) {rp.stop();} 

ऊपर बयान से पहले Thread.Sleep जोड़ें, यह ठीक काम करता है के रूप में यह पाश शुरू करने के बाद इस बयान पर अमल होगा।

public static void main(String[] a) { 
    runP rp = new Threadz().new runP(); 
    try { 
     Thread.sleep(2000); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    if(rp.num > 1) {rp.stop();} 
} 

मैंने इसे परीक्षण करने के लिए 1 बनाया है।

0

rp.num == 1 की जांच करना ठीक उसी बिंदु पर होना होगा जहां rp.num बिल्कुल एक है, जो कि असंभव है।

अपने main विधि में, आप एक थ्रेड शुरू करते हैं जो हर 200 एमएस num बढ़ाता है। इसके बाद, आप num == 1 जांचते हैं, लेकिन जब यह कोड निष्पादित किया जाता है तो उन कई कारकों पर निर्भर करता है जिन्हें आप वास्तव में नियंत्रित नहीं कर सकते (ओएस का शेड्यूलिंग आदि ...)। यह 10 एमएस के बाद हो सकता है (जहां मान 1 होगा), लेकिन 300 एमएस के बाद भी हो सकता है (जब मान पहले से ही 2 है)। इसके अलावा जब धागा ठीक से शुरू होता है तो यह अनिश्चित है। इसलिए यह भी संभव है कि आपका धागा केवल परीक्षण के बाद शुरू होता है। आप आसानी से चेक if(rp.num == 1) {rp.stop()}; को एक साधारण प्रिंट स्टेटमेंट System.out.println(rp.num) के साथ बदलकर इसका परीक्षण कर सकते हैं। यदि आप प्रिंटिंग से पहले कुछ समय के लिए अतिरिक्त इंतजार करते हैं, तो आप इस बारे में बेहतर महसूस कर सकते हैं कि मैं किस बारे में बात कर रहा हूं।

आप मान लें कि बाहर से एक runnable बंद करना चाहते हैं, मैं Observer pattern की तरह कुछ का उपयोग करने के लिए सुझाव:

class MyRunnable implements Runnable { 

    private final MyListener l; 
    private volatile boolean exit; 
    int num; 

    public MyRunnable(MyListener l) { 
     this.l = l; 
     exit = false; 
    } 

    @Override 
    public void run() { 
     while(!exit) { 
      System.out.println(t.currentThread().getName()+": "+num); 
      l.check(num++); 
      try { 
       t.sleep(200); 
      } catch(InterruptedException e) {} 
     } 
    } 

    public void stop() { 
     exit = true; 
    } 
} 

class MyListener { 

    private final threshold; 

    public MyListener(int x) { 
     this.threshold = x; 
    } 

    public void check(MyRunnable r, int num) { 
     if (num >= threshold) 
      r.stop(); 
    } 

} 

और अपने मुख्य विधि की तरह

public static void main(String[] args) { 
    MyListener l = new MyListener(1); 
    Runnable r = new MyRunnable(l); 
    new Thread(r).start(); 
} 
संबंधित मुद्दे