2010-07-07 24 views
27

क्या एक्जिक्यूटर्स द्वारा निष्पादित कार्यों को प्राथमिकता सेट करने की संभावना है? मुझे जेसीआईपी में इसके बारे में कुछ बयान मिल गए हैं लेकिन मुझे कोई उदाहरण नहीं मिल रहा है और मुझे दस्तावेज़ों से संबंधित कुछ भी नहीं मिल रहा है।जावा एक्जिक्यूटर्स: मैं कार्य प्राथमिकता कैसे सेट कर सकता हूं?

JCIP से

:

एक निष्पादन की नीति निर्दिष्ट "क्या, कहां, कब और कैसे" कार्य निष्पादन की, जिनमें शामिल हैं:

  • ...
  • क्या में ऑर्डर को निष्पादित किया जाना चाहिए (फीफो, लिफो, प्राथमिकता आदेश)?
  • ...

युपीडी: मुझे एहसास हुआ कि मैंने पूछा कि वास्तव में क्या नहीं मैं पूछने के लिए करना चाहता था। मैं वास्तव में क्या चाहता था:

निष्पादक ढांचे के साथ सेटिंग थ्रेड प्राथमिकता का उपयोग/अनुकरण कैसे करें (यानी thread.setPriority() क्या था)?

उत्तर

48

वर्तमान में the Executor interface का केवल ठोस कार्यान्वयन the ThreadPoolExecutor और the ScheduledThreadpoolExecutor

उपयोगिता/कारखाने वर्ग Executors का उपयोग कर के बजाय, आप एक उदाहरण एक निर्माता का उपयोग कर बनाने चाहिए रहे हैं।

आप ThreadPoolExecutor के निर्माता को BlockingQueue पास कर सकते हैं।

ब्लॉकिंगक्यूयू, the PriorityBlockingQueue के कार्यान्वयन में से एक आपको एक कन्स्ट्रेटर को एक कन्स्ट्रक्टर को पास करने देता है, जिससे आप निष्पादन के आदेश का निर्णय ले सकें।

+3

+1 PriorityBlockingQueue जाने का रास्ता है। आप एक तुलनात्मक को कार्यान्वित कर सकते हैं या कार्यों को खुद को तुलनात्मक बना सकते हैं। –

+2

यह आलेख एक महान संदर्भ है: http://binkley.blogspot.fr/2009/04/jumping-work-queue-in-executor.html – Snicolas

+0

मेरा समाधान प्राथमिकता से कार्यों का आदेश देता है, लेकिन समान प्राथमिकता स्तर पर आदेश सबमिट करना: http://stackoverflow.com/a/42831172/1386911 –

0

साथ ThreadPoolExecutor का उपयोग कृपया ध्यान रखें कि setPriority (..) सामान्य रूप से लिनक्स के तहत नहीं काम करता है हो सकता है। पूरी जानकारी के लिए निम्न लिंक देखें:

+2

टिप्पणियां टिप्पणियां हैं; जवाब उत्तर हैं। टिप्पणियां उत्तर नहीं हैं। उत्तर टिप्पणी नहीं हैं। यदि यह पूछे जाने वाले प्रश्न का उत्तर नहीं देता है, तो वास्तव में, यह एक टिप्पणी है। –

+0

+1 @ निक - हा हा, इसे प्यार करो!एक शब्द का उपयोग क्यों करें जब आप लंबी, सार्क टिप्पणी का उपयोग कर सकें। अच्छा बिंदु और अच्छी तरह से (cheekily) बनाया। – TedTrippin

2

आप ThreadPoolExecutor निर्माता (या Executors कारखाने विधि) में एक ThreadFactory निर्दिष्ट कर सकते हैं। यह आपको निष्पादक के लिए दी गई थ्रेड प्राथमिकता के थ्रेड प्रदान करने की अनुमति देता है।

विभिन्न नौकरियों के लिए अलग-अलग थ्रेड प्राथमिकताओं को प्राप्त करने के लिए, आपको उन्हें विभिन्न थ्रेड कारखानों के साथ निष्पादकों को भेजने की आवश्यकता होगी।

30

यहां विचार यह है कि निष्पादक में प्राथमिकताब्लॉकिंग क्यूयू का उपयोग करना है। इसके लिए:

  • एक तुलनात्मक बनाएं जो हमारे वायदा की तुलना करेगा।
  • प्राथमिकता रखने के लिए भविष्य के लिए प्रॉक्सी बनाएं।
  • हमारे प्रॉक्सी में हर भविष्य को लपेटने के लिए 'newTaskFor' को ओवरराइड करें।

सबसे पहले आप अपने भविष्य पर प्राथमिकता पकड़ की जरूरत है:

class PriorityFutureComparator implements Comparator<Runnable> { 
    public int compare(Runnable o1, Runnable o2) { 
     if (o1 == null && o2 == null) 
      return 0; 
     else if (o1 == null) 
      return -1; 
     else if (o2 == null) 
      return 1; 
     else { 
      int p1 = ((PriorityFuture<?>) o1).getPriority(); 
      int p2 = ((PriorityFuture<?>) o2).getPriority(); 

      return p1 > p2 ? 1 : (p1 == p2 ? 0 : -1); 
     } 
    } 
} 

अगला मान लेते हैं कि हम एक डालते हैं:

class PriorityFuture<T> implements RunnableFuture<T> { 

    private RunnableFuture<T> src; 
    private int priority; 

    public PriorityFuture(RunnableFuture<T> other, int priority) { 
     this.src = other; 
     this.priority = priority; 
    } 

    public int getPriority() { 
     return priority; 
    } 

    public boolean cancel(boolean mayInterruptIfRunning) { 
     return src.cancel(mayInterruptIfRunning); 
    } 

    public boolean isCancelled() { 
     return src.isCancelled(); 
    } 

    public boolean isDone() { 
     return src.isDone(); 
    } 

    public T get() throws InterruptedException, ExecutionException { 
     return src.get(); 
    } 

    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 
     return src.get(); 
    } 

    public void run() { 
     src.run(); 
    } 
} 

इसके बाद आप तुलनित्र कि सही ढंग से प्राथमिकता वायदा सॉर्ट हैं परिभाषित करने की जरूरत इस तरह की लंबी नौकरी:

class LenthyJob implements Callable<Long> { 
    private int priority; 

    public LenthyJob(int priority) { 
     this.priority = priority; 
    } 

    public Long call() throws Exception { 
     System.out.println("Executing: " + priority); 
     long num = 1000000; 
     for (int i = 0; i < 1000000; i++) { 
      num *= Math.random() * 1000; 
      num /= Math.random() * 1000; 
      if (num == 0) 
       num = 1000000; 
     } 
     return num; 
    } 

    public int getPriority() { 
     return priority; 
    } 
} 

फिर क्रम प्राथमिकता में इन नौकरियों पर अमल करने में कोड दिखेगा की तरह:

public class TestPQ { 

    public static void main(String[] args) throws InterruptedException, ExecutionException { 
     int nThreads = 2; 
     int qInitialSize = 10; 

     ExecutorService exec = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, 
       new PriorityBlockingQueue<Runnable>(qInitialSize, new PriorityFutureComparator())) { 

      protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { 
       RunnableFuture<T> newTaskFor = super.newTaskFor(callable); 
       return new PriorityFuture<T>(newTaskFor, ((LenthyJob) callable).getPriority()); 
      } 
     }; 

     for (int i = 0; i < 20; i++) { 
      int priority = (int) (Math.random() * 100); 
      System.out.println("Scheduling: " + priority); 
      LenthyJob job = new LenthyJob(priority); 
      exec.submit(job); 
     } 
    } 
} 

इस कोड का एक बहुत कुछ है, लेकिन है कि लगभग एक ही तरीका है यह पूरा किया जा सकता है।

मेरी मशीन पर आउटपुट निम्नलिखित की तरह है:

Scheduling: 39 
Scheduling: 90 
Scheduling: 88 
Executing: 39 
Scheduling: 75 
Executing: 90 
Scheduling: 15 
Scheduling: 2 
Scheduling: 5 
Scheduling: 24 
Scheduling: 82 
Scheduling: 81 
Scheduling: 3 
Scheduling: 23 
Scheduling: 7 
Scheduling: 40 
Scheduling: 77 
Scheduling: 49 
Scheduling: 34 
Scheduling: 22 
Scheduling: 97 
Scheduling: 33 
Executing: 2 
Executing: 3 
Executing: 5 
Executing: 7 
Executing: 15 
Executing: 22 
Executing: 23 
Executing: 24 
Executing: 33 
Executing: 34 
Executing: 40 
Executing: 49 
Executing: 75 
Executing: 77 
Executing: 81 
Executing: 82 
Executing: 88 
Executing: 97 
+0

जबकि * स्वीकृत उत्तर * प्रश्न का उत्तर देता है यह एक कार्य समाधान प्रदान करता है। बहुत बहुत धन्यवाद। – m02ph3u5

+0

आपके उत्तर के लिए धन्यवाद। क्या execorCompletionService के साथ इस दृष्टिकोण का उपयोग करना संभव होगा? मैंने आपके एक्जिक्यूटर्स सेवा ऑब्जेक्ट में एक्जिक्यूटर कॉम्प्लिशन सर्विस कन्स्ट्रक्टर में पास करने का प्रयास किया लेकिन परिणाम तुलनित्र में प्राथमिकता भविष्य में नहीं डाला जा सकता है। – Arash

+0

मैंने अपनी मशीन पर परीक्षण किया। यह सही नहीं है। मेरी मशीन पर, मुझे 3 निष्पादन से पहले 72 निष्पादित किया गया, जो स्पष्ट रूप से गलत है। –

0

बस इस चर्चा करने के लिए योगदान के अपने बिट जोड़ना चाहते हैं। मैंने इस ReorderingThreadPoolExecutor को एक बहुत ही विशिष्ट उद्देश्य के लिए कार्यान्वित किया है, जो कि जब भी मैं चाहता हूं और प्राथमिकताओं से निपटने के बिना निष्पादक के ब्लॉकिंगक्यूयू (इस मामले में लिंक्डब्लॉकिंग डेक) के सामने स्पष्ट रूप से सामने आ सकता है (जो डेडलॉक्स का कारण बन सकता है और , वैसे भी, तय)।

मैं इसे प्रबंधित करने के लिए इसका उपयोग कर रहा हूं (एंड्रॉइड ऐप के अंदर) जहां मुझे एक लंबी सूची दृश्य में प्रदर्शित कई छवियां डाउनलोड करनी होंगी। जब भी उपयोगकर्ता जल्दी से नीचे स्क्रॉल करता है, निष्पादक कतार छवि डाउनलोड अनुरोधों में बाढ़ आती है: कतार के शीर्ष पर नवीनतम लोगों को स्थानांतरित करके, मैंने वास्तव में स्क्रीन पर मौजूद छवियों को लोड करने में बहुत बेहतर प्रदर्शन प्राप्त किए हैं, डाउनलोड में देरी जिनकी शायद बाद में आवश्यकता होगी। ध्यान दें कि मैं निष्पादक को कार्यों को जोड़ने के लिए एक आंतरिक समवर्ती मानचित्र कुंजी (जो छवि यूआरएल स्ट्रिंग के रूप में सरल हो सकता है) का उपयोग करता हूं ताकि मैं उन्हें बाद में पुनर्वितरण के लिए पुनर्प्राप्त कर सकूं।

ऐसा करने के कई अन्य तरीके होंगे और शायद यह जटिल है, लेकिन यह ठीक काम करता है और फेसबुक अपने एंड्रॉइड एसडीके में भी अपने कामकाजी धागे कतार में कुछ ऐसा कर रहा है।

कोड पर एक नजर है और मुझे सुझाव दे के लिए स्वतंत्र महसूस, यह एक Android परियोजना के अंदर है, लेकिन कुछ लॉग और एनोटेशन अलग करना वर्ग शुद्ध जावा 6.

0

आप अपनी खुद की ThreadFactory लागू कर सकते हैं बनाना होगा और सेट इस तरह यह ThreadPoolExecutor भीतर:

ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, numOfWorkerThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); 
threadPool.setThreadFactory(new OpJobThreadFactory(Thread.NORM_PRIORITY-2)); 

जहाँ मेरे OpJobThreadFactory ऐसा दिखाई देता है:

public final static class OpJobThreadFactory implements ThreadFactory { 
    private int priority; 
    private boolean daemon; 
    private final String namePrefix; 
    private static final AtomicInteger poolNumber = new AtomicInteger(1); 
    private final AtomicInteger threadNumber = new AtomicInteger(1); 

    public OpJobThreadFactory(int priority) { 
     this(priority, true); 
    } 

    public OpJobThreadFactory(int priority, boolean daemon) { 
     this.priority = priority; 
     this.daemon = daemon; 
     namePrefix = "jobpool-" +poolNumber.getAndIncrement() + "-thread-"; 
    } 

    @Override 
    public Thread newThread(Runnable r) { 
     Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement()); 
     t.setDaemon(daemon); 
     t.setPriority(priority); 
     return t; 
    } 
} 
संबंधित मुद्दे