2012-02-26 13 views
6

मैं एक जावा इटरेटर पर एक साथ लूप करने की कोशिश कर रहा हूं, लेकिन ऐसा करने के सर्वोत्तम तरीके से परेशानी हो रही है।जावा इटरेटर कंसुरेंसी

यहां मेरे पास है जहां मैं समवर्ती रूप से कुछ भी करने की कोशिश नहीं करता हूं।

Long l;  
Iterator<Long> i = getUserIDs(); 

while (i.hasNext()) { 
    l = i.next(); 

    someObject.doSomething(l); 
    anotheObject.doSomething(l); 
} 

बातें मैं गैर इटरेटर वस्तुओं पर कर रहा हूँ के बीच कोई दौड़ की स्थिति होनी चाहिए, इसलिए मैं इस बारे में भी चिंतित नहीं हूँ। मैं बस तेज़ करना चाहता हूं कि इसे अनुक्रमिक रूप से ऐसा नहीं कर रहा है।

अग्रिम धन्यवाद।

उत्तर

4

एक समाधान आपके कार्य को समानांतर करने के लिए एक निष्पादक का उपयोग करना है।

सरल उदाहरण:

ExecutorService executor = Executors.newCachedThreadPool(); 

Iterator<Long> i = getUserIDs(); 
while (i.hasNext()) { 
    final Long l = i.next(); 

    Runnable task = new Runnable() { 
     public void run() { 
      someObject.doSomething(l); 
      anotheObject.doSomething(l); 
     } 
    } 

    executor.submit(task); 
} 

executor.shutdown(); 

यह इटरेटर में प्रत्येक आइटम है, जो तब काम करेंगे के लिए एक नया धागा पैदा करेगा। आप Executors कक्षा पर एक अलग विधि का उपयोग करके कितने धागे का उपयोग कर सकते हैं, या फिट के रूप में काम को उप-विभाजित कर सकते हैं (उदाहरण के लिए प्रत्येक विधि कॉल के लिए एक अलग Runnable)।

5

एक दो संभावित दृष्टिकोण की पेशकश कर सकते हैं:

  • एक थ्रेड पूल का प्रयोग करें और प्रेषण आइटम प्रसंस्करण धागे का एक सेट करने के लिए पुनरावर्तक से प्राप्त किया। इससे इटेटर ऑपरेशन को तेज़ नहीं किया जाएगा, क्योंकि वे अभी भी एक थ्रेड में होंगे, लेकिन यह वास्तविक प्रसंस्करण को समानांतर करेगा।

  • कैसे यात्रा बनाई गई है इसके आधार पर आप विभाजित करने के लिए एक से अधिक खंडों के लिए यात्रा की प्रक्रिया में सक्षम हो सकता है, प्रत्येक एक अलग Iterator वस्तु के माध्यम से एक अलग थ्रेड द्वारा संसाधित किया जा करने के लिए। उदाहरण के लिए, List.sublist(int fromIndex, int toIndex) और List.listIterator(int index) विधियों पर एक नज़र डालें।

    यह इटरेटर ऑपरेशंस समानांतर में होने की अनुमति देगा, लेकिन इस तरह के पुनरावृत्ति को विभाजित करना हमेशा संभव नहीं होता है, आमतौर पर साधारण तथ्य यह है कि वस्तुओं को फिर से चालू नहीं किया जाता है।

  • बोनस चाल के रूप में, यदि पुनरावृत्ति संचालन महंगे या धीमे होते हैं, जैसे कि डेटाबेस तक पहुंचने के लिए आवश्यक, तो आप एक थ्रूपुट सुधार देख सकते हैं यदि आप उन्हें अलग थ्रेड पर अलग करते हैं जो इटरेटर को भरने के लिए उपयोग करेगा BlockingQueue में। डिस्पैचर थ्रेड को केवल अगले आइटम को पुनर्प्राप्त करने के लिए इटरेटर ऑब्जेक्ट पर इंतजार किए बिना कतार तक पहुंचना होगा।

इस मामले में सबसे महत्वपूर्ण सलाह यह है: , आमतौर पर द्वारा अपनाई जाने वाली "अपने प्रोफाइलर का प्रयोग करें" "समय से पहले अनुकूलन मत करो"। एक प्रोफाइलर का उपयोग करके, जैसे VisualVM, आपको सटीक किसी भी प्रदर्शन समस्याओं के कारण, अंधेरे में शॉट्स लेने के बिना पता लगाने में सक्षम होना चाहिए।

1

यदि आप जावा 7 का उपयोग कर रहे हैं, तो आप नए फोर्क/जॉइन का उपयोग कर सकते हैं; tutorial देखें।

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

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