2012-09-25 22 views
5

द्वारा अधिसूचित किए जाने तक मैं बहु-थ्रेडिंग के लिए नया हूं और जब मैं बहु थ्रेडिंग के बारे में पढ़ रहा हूं, तो निम्नलिखित करने के लिए इस फैंसी मल्टी-थ्रेडिंग कोड को लिखने का विचार।thread1 से कैसे प्रतीक्षा करें थ्रेड 2

मेरी काउंटर क्लास निम्नानुसार है।

class Counter { 
    private int c = 0; 

    public void increment() { 
    System.out.println("increment value: "+c); 
     c++; 
    } 

    public void decrement() { 
     c--; 
     System.out.println("decrement value: "+c); 
    } 

    public int value() { 
     return c; 
    } 

} 

यह काउंटर ऑब्जेक्ट दो धागे के बीच साझा किया जाता है। एक बार थ्रेड शुरू हो जाने के बाद, मुझे निम्न कार्य करने की आवश्यकता है। मैं थ्रेड 2 को तब तक प्रतीक्षा करना चाहता हूं जब तक थ्रेड 1 काउंटर ऑब्जेक्ट की गिनती को 1 द्वारा बढ़ाए जाने के बाद, थ्रेड 1 थ्रेड 2 को सूचित करता है और फिर थ्रेड 1 थ्रेड 2 के लिए 1/ द्वारा मूल्य मान के लिए प्रतीक्षा करना शुरू करता है तो थ्रेड 2 शुरू होता है और घटता है 1 तक और थ्रेड 1 को फिर से सूचित करता है और फिर थ्रेड 2 थ्रेड 1 के लिए प्रतीक्षा करना शुरू कर देता है। इस प्रक्रिया को कुछ बार दोहराएं।

मैं इसे कैसे प्राप्त कर सकता हूं। अग्रिम में बहुत धन्यवाद।

मैंने निम्नलिखित किया है।

public class ConcurrencyExample { 

    private static Counter counter; 
    private static DecrementCount t1; 
    private static IncrementCount t2; 

    public static void main(String[] args) { 
    Counter counter = new Counter(); 
    Thread t1 = new Thread(new IncrementCount(counter)); 
    t1.start(); 

    Thread t2 = new Thread(new DecrementCount(counter)); 
    t2.start(); 

    } 

} 


public class DecrementCount implements Runnable { 

    private static Counter counter; 

    public DecrementCount(Counter counter) { 
    this.counter = counter; 
    } 

    @Override 
    public void run() { 
    for (int i = 0; i < 1000; i++) { 
     counter.decrement();  
     System.out.println("decreamented"); 
    } 
    } 

} 


public class IncrementCount implements Runnable { 

    private static Counter counter; 

    public IncrementCount(Counter counter) { 
    this.counter = counter; 
    } 

    @Override 
    public void run() { 
    for (int i = 0; i < 1000; i++) { 
     counter.increment(); 
     System.out.println("Incremented"); 
    } 

    } 

} 
+2

काउंटरडाउन देखें: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html – davidmontoyago

+1

'वृद्धि काउंटर' को 'increment()' कॉल करना चाहिए, है ना? –

+1

ऐसा करने का सबसे आसान तरीका एक थ्रेड का उपयोग करना होगा। मेरा सुझाव है कि आप उन उदाहरणों पर विचार करें जहां एकाधिक धागे का उपयोग करना अधिक जटिल और धीमी गति से अधिक तेज़ होगा। –

उत्तर

3

Semaphore देखें। आपको प्रत्येक थ्रेड के लिए दो, एक की आवश्यकता होगी: incSemaphore और decSemaphoreDecrementCount में कार्य करें:

for (int i = 0; i < 1000; i++) { 
    decSemaphore.acquire(); 
    counter.decrement();  
    System.out.println("decreamented"); 
    incSemaphore.release(); 
} 

संतुलित लागू IncrementCountincSemaphore का प्रारंभिक मान 1 और 0decSemaphore के लिए होना चाहिए।

BTW अपने Counter रूप में अच्छी तरह तुल्यकालन की आवश्यकता है (synchronized कीवर्ड और AtomicInteger देखें)।

+0

+1। – dcernahoschi

0

बूलियन ध्वज के साथ Condition का उपयोग करें।

final Lock lock = new ReentrantLock(); 
final Condition incremented= lock.newCondition(); 
final Condition decremented= lock.newCondition(); 

नीचे

स्पष्टीकरण के लिए अपने काउंटर बदलें:

हम दो स्थितियों का इस्तेमाल किया है एक वृद्धि की जाती है और एक कम कर रहा है। बुलियन ध्वज के आधार पर हम जांच करते हैं कि हमें एक शर्त पर इंतजार करना है या नहीं।

class Counter { 
private int c = 0; 
boolean increment = false; 

final Lock lock = new ReentrantLock(); 
final Condition incremented = lock.newCondition(); 
final Condition decremented = lock.newCondition(); 

public void increment() throws InterruptedException { 
    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     while(increment) 
      decremented.await(); 
     increment = true;   
     c++; 
     System.out.println("increment value: " + c); 
     incremented.signal(); 
    } finally { 
     lock.unlock(); 
    } 

} 

public void decrement() throws InterruptedException { 

    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     while (!increment) 
      incremented.await(); 
     c--; 
     System.out.println("decrement value: " + c); 
     increment = false; 
     decremented.signal(); 
    } finally { 
     lock.unlock(); 
    } 
} 

public int value() { 
    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     return c; 
    } finally { 
     lock.unlock(); 
    } 
} 

} 
+0

क्या कोई एक -1 को समझा सकता है? –

+0

प्रारंभ में उत्तर उपयोगी से कम था। अब बेहतर है। – Gray

+0

@ ग्रे प्रदान कोड भी। स्पष्टता के लिए –

0

- सबसे पहले अपने increment() और decrement() स्थिति यह ब्रायन शासन देखें

When we write a variable which has just been read by another thread, or reading a variable which is just lately written by another thread, must be using Synchronization. And those atomic statements/Methods accessing the fields' data must be also synchronized.

synchronized कीवर्ड का उपयोग दौड़ से बचने के लिए किया जाना चाहिए - इसके JVM Thread Scheduler है नियंत्रण कौन सा धागा रनिंग स्टेट में प्रवेश करेगा, यह कितना समय तक रहेगा, और इसके काम के बाद यह कहाँ जाएगा।

- एक Cannot be sure जिनमें से धागा पहले चलेंगे .....

- तुम भी java.util.concurrent से SingleThreadExecutor उपयोग कर सकते हैं, इस दूसरे पर जाने से पहले एक कार्य को पूरा करता।

+0

आप ब्रायन के शासन को गलत समझते हैं और यह वैसे भी सही नहीं है। वाष्पशीलता का उपयोग भी एक समाधान है। –

+0

@ मार्टिनसेरानो सबसे पहले यदि आपके पास दस्तावेज नहीं है तो कुछ कथन के बारे में सबूत गलत है, इसे गलत मत समझो। दूसरा, कृपया ब्रूस ईकल द्वारा जावा बुक में थिंकिंग के थ्रेडिंग अध्याय के चौथे संस्करण का संदर्भ लें यदि आपको कोई संदेह है ... अब ब्रायन नियम जो मैंने लिखा है वह सही है, और मुझे लगता है कि आपने अभी तक पर्याप्त अस्थिरता के साथ खेला नहीं है। एक क्षेत्र अस्थिर बनाना सुनिश्चित नहीं करता है कि उस क्षेत्र तक पहुंचने वाले बयान एकल परमाणु बयान ..... –