2011-12-07 25 views
9

जावा अनुसूचित अधिकारियों का उपयोग करते समय मुझे एक विशिष्टता मिली और मुझे आश्चर्य हुआ कि मैंने जो अनुभव किया वह सामान्य है।जावा अनुसूचित निष्पादक सटीकता

मुझे उन कार्यों को शेड्यूल करने की आवश्यकता है जो 5 सेकंड की पूर्वनिर्धारित दर पर निष्पादित हों। यह अपेक्षा की जाती है कि इन कार्यों को समय-समय पर निष्पादित करने में 5 सेकंड से अधिक समय लगेगा, लेकिन जब उन्हें चलाने का समय 5 सेकंड से नीचे चला जाता है, तो कार्यों की बैक अप सूची को पकड़ने के लिए त्वरित उत्तराधिकार में चलना चाहिए। कार्यों को चलाने के दौरान, यह जानना महत्वपूर्ण है कि मूल अनुसूचित निष्पादन समय क्या था (scheduledExecutionTime()java.util.TimerTask में सोचें)। आखिरकार, अनुसूची समय और वास्तविक समय के बीच अंतर को ट्रैक करने की आवश्यकता है ताकि यह निर्धारित किया जा सके कि शेड्यूल "बहती" कब और कितनी है।

अब तक मैं जावा निष्पादकों का उपयोग करके इस सब को लागू किया है, और निम्न वर्ग सामान्य विचार दिखाता है:

public class ExecutorTest { 
    public static final long PERIOD = 5000; 

    public static void main(String[] args) { 
     Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
       new Command(), 0, PERIOD, TimeUnit.MILLISECONDS); 
    } 

    private static final class Command implements Runnable { 
     long timestamp = 0; 

     public void run() { 
      long now = System.currentTimeMillis(); 

      if (timestamp == 0) { 
       timestamp = now; 
      } 

      // Drift is the difference between scheduled time and execution time 
      long drift = now - timestamp; 

      String format = "Ran at %1$tF %<tT,%<tL; drift: %2$dms"; 
      System.out.println(String.format(format, now, drift)); 

      timestamp += PERIOD; 
     } 
    } 
} 

ऊपर सूचीबद्ध कोड चल रहा है पता चलता है कि बहाव (जो आदर्श के नजदीक होना चाहिए 0 जितना संभव हो) कुछ सेकंड तक उतार-चढ़ाव करता है, जिसके परिणामस्वरूप कार्य समय-समय पर या देर से निष्पादित होते हैं। मैं लगभग 150 मिनट के लिए इस चलाने के परिणामों से एक ग्राफ बनाया है:

Java executor drift

तो मेरा पहला सवाल यह है कि यह सामान्य है है। मेरे पर्यावरण में 32 बिट विंडोज एक्सपी और जावा 1.5 अपडेट 21 शामिल हैं (हालांकि जावा 6 अपडेट 22 इसी तरह के परिणाम उत्पन्न करता है)।

दूसरा सवाल यह है कि बहाव की मात्रा को कम करने का एक आसान तरीका है या नहीं। यदि मैं एक साधारण java.util.Timer या यहां तक ​​कि केवल Thread.sleep() का उपयोग करता हूं, तो बहाव अस्तित्व में नहीं है।

आखिरकार, नियत निष्पादकों का उपयोग करते समय निर्धारित निष्पादन समय को ट्रैक करने का एक बेहतर तरीका है?

उत्तर

8

निर्धारित निष्पादक सेवा System.nanoTime का उपयोग करती है जो वर्तमान टाइममिलिस जितनी अधिक नहीं जाती है। सिवाय इसके कि यदि आप एक से अधिक CPU सॉकेट वाले XP सिस्टम पर चल रहे हैं। एक्सपी में एक बग है जहां ओएस कॉल सिस्टम.नानोटाइम() का उपयोग सॉकेट के बीच संगत नहीं है, क्योंकि थ्रेड स्विच करता है, जिस पर यह सॉकेट चल रहा है, आप इस कूद को चारों ओर देखने की उम्मीद कर सकते हैं। (यह Vista/7 पर कोई समस्या नहीं है)

एक सॉकेट के साथ एक लिनक्स सिस्टम पर आपका प्रोग्राम 0 - 3 एमएस बहाव रिपोर्ट करता है।

इस कार्यक्रम को आजमाएं।

public static void main(String... args) throws Exception { 
    long start = System.nanoTime(); 
    long time = start; 
    while(time < start + 3e10) { 
     long now = System.nanoTime(); 
     if (now < time || now > time + 50000) { 
      System.out.println(now - time); 
      now = System.nanoTime(); 
     } 
     time = now; 
    } 
} 

एक i7 प्रणाली पर मैं जो 2 एमएस की लगभग 10 छलांग देखते हैं। अगर मैं मशीन का उपयोग करता हूं तो मैं और देखता हूं। मुझे उम्मीद है कि आप देख सकते हैं कि यह बड़ा नकारात्मक और सकारात्मक समय है।

0

मेरे लिए सामान्य लगता है, यह 5000/2 की सीमा में भिन्न होता है। प्रारूप के चरण में + println आपको तेजी से लॉगिंग करने की कोशिश करनी चाहिए, इसलिए println का ओवरहेड बहाव माप नहीं है। दिलचस्प होगा।

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