2012-05-26 39 views
5

के साथ countDownLatch.await (int) के लिए एकाधिक कॉल मैं किसी अन्य घटक (एक अलग थ्रेड में चल रहे) से किसी निश्चित ईवेंट की प्रतीक्षा के लिए काउंटरडाउनलैच का उपयोग करता हूं। निम्नलिखित दृष्टिकोण अपने सॉफ़्टवेयर के शब्दों फिट होगा, लेकिन मुझे यकीन है कि क्या यह एक के रूप में काम मैं उम्मीद नहीं कर रहा हूँ:टाइमआउट

mCountDownLatch.await(3000, TimeUnit.MILLISECONDS) 
otherComponent.aStaticVolatileVariable = true; 
mCountDownLatch.await(3500, TimeUnit.MILLISECONDS); 
... <proceed with other stuff> 

परिदृश्य निम्नलिखित होना चाहिए: मैं 3 सेकंड के लिए प्रतीक्षा करें, और यदि कुंडी है 0 तक गिनती नहीं है, मैं उस चर के साथ दूसरे घटक को सूचित करता हूं, और फिर मैं 3.5 सेकंड तक प्रतीक्षा करता हूं। यदि फिर से टाइमआउट है, तो मुझे परवाह नहीं है और अन्य परिचालनों के साथ आगे बढ़ेगा।

नोट: मुझे पता है कि यह ऐसा नहीं दिखता है, लेकिन उपर्युक्त परिदृश्य मेरे सॉफ़्टवेयर में पूरी तरह से उचित और मान्य है।

मैंने प्रतीक्षा (int, TimeUnit) और CountDownLatch के दस्तावेज़ को पढ़ा है, लेकिन मैं जावा/एंड्रॉइड विशेषज्ञ नहीं हूं, इसलिए मुझे पुष्टि की आवश्यकता है। मेरे लिए, सभी स्थितियों वैध देखो:

  • पहले इंतजार सफल होता है, तो अन्य तुरंत वापस आ जाएगी
  • पहले इंतजार का समय समाप्त, तो अन्य इंतजार अभी भी मान्य है, तो इंतजार है; इसलिए, अन्य धागा स्थिर संकेत गौर करता है, दूसरा इंतजार वापस कर सकती है सफलतापूर्वक
  • दोनों का इंतजार कॉल समय बाहर (यह मेरा सॉफ्टवेयर के अर्थ विज्ञान के अनुसार ठीक है)

मैं इंतजार का उपयोग कर रहा हूँ (.. सही ढंग से? क्या दूसरी प्रतीक्षा (...) उपर्युक्त तरीके से उपयोग की जा सकती है भले ही एक ही ऑब्जेक्ट पर पिछले प्रतीक्षा (...) का समय समाप्त हो गया हो?

उत्तर

4

यदि मैं आपका प्रश्न सही ढंग से समझता हूं, तो यह परीक्षण साबित करता है कि आपकी सभी मान्यताओं/आवश्यकताओं को सत्य/पूरा किया गया है। (JUnit और Hamcrest साथ चलाएँ।) runCodeUnderTest() विधि में अपने कोड नोट, हालांकि यह समय रिकॉर्डिंग के साथ बीच-बीच में है और समय समाप्ति बहुत ही गहन कोड के लिए की 10.

import org.junit.Before; 
import org.junit.Test; 

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.TimeUnit; 

import static org.hamcrest.Matchers.closeTo; 
import static org.hamcrest.Matchers.lessThan; 
import static org.junit.Assert.assertThat; 

public class CountdownLatchTest { 
    static volatile boolean signal; 
    CountDownLatch latch = new CountDownLatch(1); 
    long elapsedTime; 
    long[] wakeupTimes = new long[2]; 

    @Before 
    public void setUp() throws Exception { 
     signal = false; 
    } 

    @Test 
    public void successfulCountDownDuringFirstAwait() throws Exception { 
     countDownAfter(150); 
     runCodeUnderTest(); 
     assertThat((double) elapsedTime, closeTo(150, 10)); 
     assertThat(wakeupTimeSeparation(), lessThan(10)); 
    } 

    @Test 
    public void successfulCountDownDuringSecondAwait() throws Exception { 
     countDownAfter(450); 
     runCodeUnderTest(); 
     assertThat((double) elapsedTime, closeTo(450, 10)); 
     assertThat((double) wakeupTimeSeparation(), closeTo(150, 10)); 
    } 

    @Test 
    public void neverCountDown() throws Exception { 
     runCodeUnderTest(); 
     assertThat((double) elapsedTime, closeTo(650, 10)); 
     assertThat((double) wakeupTimeSeparation(), closeTo(350, 10)); 
    } 

    @Test 
    public void countDownAfterSecondTimeout() throws Exception { 
     countDownAfter(1000); 
     runCodeUnderTest(); 
     assertThat((double) elapsedTime, closeTo(650, 10)); 
     assertThat((double) wakeupTimeSeparation(), closeTo(350, 10)); 
    } 

    @Test 
    public void successfulCountDownFromSignalField() throws Exception { 
     countDownAfterSignal(); 
     runCodeUnderTest(); 
     assertThat((double) elapsedTime, closeTo(300, 10)); 
    } 

    private int wakeupTimeSeparation() { 
     return (int) (wakeupTimes[1] - wakeupTimes[0]); 
    } 

    private void runCodeUnderTest() throws InterruptedException { 
     long start = System.currentTimeMillis(); 
     latch.await(300, TimeUnit.MILLISECONDS); 
     wakeupTimes[0] = System.currentTimeMillis(); 
     signal = true; 
     latch.await(350, TimeUnit.MILLISECONDS); 
     wakeupTimes[1] = System.currentTimeMillis(); 
     elapsedTime = wakeupTimes[1] - start; 
    } 

    private void countDownAfter(final long millis) throws InterruptedException { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       sleep(millis); 
       latch.countDown(); 
      } 
     }).start(); 
    } 

    private void countDownAfterSignal() { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       boolean trying = true; 
       while (trying) { 
        if (signal) { 
         latch.countDown(); 
         trying = false; 
        } 
        sleep(5); 
       } 
      } 
     }).start(); 
    } 

    private void sleep(long millis) { 
     try { 
      Thread.sleep(millis); 
     } catch (InterruptedException e) { 
      throw new IllegalStateException("Unexpected interrupt", e); 
     } 
    } 
} 
+0

धन्यवाद एक पहलू से कमी आती है। असल में, मेरा सवाल इससे कहीं अधिक सरल था, लेकिन अगर मैं सही हूं, तो आप वास्तव में * साबित हुए हैं कि मेरी धारणाएं सही हैं, इसलिए इसके लिए एक बड़ा धन्यवाद! मेरा मूल प्रश्न केवल यही था: यदि किसी ऑब्जेक्ट के लिए पहला इंतजार ** (** ** टाइम्स ** है, तो क्या मैं उसी ऑब्जेक्ट (जैसे मेरे कोड में) पर फिर से प्रतीक्षा कर सकता हूं? मुझे हां लगता है, लेकिन जैसा कि मैंने कहा, मैं जावा विशेषज्ञ नहीं हूं। (मुझे अंतिम पुष्टि मिलने के बाद, मैं निश्चित रूप से आपके उत्तर को उत्तर के रूप में चिह्नित करूंगा, क्योंकि यह मेरी आवश्यकता से अधिक है।) –

+1

हे, ईमानदार होने के लिए, मैं 100% उत्तर के ऊपर से कुछ जवाब नहीं था मेरे सिर, और इस तरह का जवाब खोजने का सबसे अच्छा तरीका यह है कि इसे आजमाएं। इसलिए परीक्षण :) –

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