2011-02-10 13 views
9

कार्य पूरा होने तक किसी और अनुरोध को छोड़कर मुझे एक कार्य को अतुल्यकालिक रूप से निष्पादित करने की आवश्यकता है।आगे के अनुरोधों को कतारबद्ध किए बिना एक कार्य को थ्रेड करना

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

एकमात्र चीज जो मैं सोच सकता हूं वह कतार को अवरुद्ध करने के लिए सेमफोर का उपयोग करना है। मैं यह दिखाने के लिए निम्नलिखित उदाहरण के साथ आया हूं कि मैं क्या हासिल करने की कोशिश कर रहा हूं। क्या कोई आसान तरीका है? क्या मुझे कुछ स्पष्ट याद आया है?

import java.util.concurrent.*; 

public class ThreadPoolTester { 
    private static ExecutorService executor = Executors.newSingleThreadExecutor(); 
    private static Semaphore processEntry = new Semaphore(1); 

    public static void main(String[] args) throws InterruptedException { 
     for (int i = 0; i < 20; i++) { 
      kickOffEntry(i); 

      Thread.sleep(200); 
     } 

     executor.shutdown(); 
    } 

    private static void kickOffEntry(final int index) { 
     if (!processEntry.tryAcquire()) return; 
     executor. 
      submit(
       new Callable<Void>() { 
        public Void call() throws InterruptedException { 
         try { 
          System.out.println("start " + index); 
          Thread.sleep(1000); // pretend to do work 
          System.out.println("stop " + index); 
          return null; 

         } finally { 
          processEntry.release(); 
         } 
        } 
       } 
      ); 
    } 
} 

नमूना उत्पादन

start 0 
stop 0 
start 5 
stop 5 
start 10 
stop 10 
start 15 
stop 15 

axtavt का जवाब ले रहा है और ऊपर के उदाहरण बदलने निम्नलिखित सरल समाधान देता है।

import java.util.concurrent.*; 

public class SyncQueueTester { 
    private static ExecutorService executor = new ThreadPoolExecutor(1, 1, 
      1000, TimeUnit.SECONDS, 
      new SynchronousQueue<Runnable>(), 
      new ThreadPoolExecutor.DiscardPolicy()); 

    public static void main(String[] args) throws InterruptedException { 
     for (int i = 0; i < 20; i++) { 
      kickOffEntry(i); 

      Thread.sleep(200); 
     } 

     executor.shutdown(); 
    } 

    private static void kickOffEntry(final int index) { 
     executor. 
      submit(
       new Callable<Void>() { 
        public Void call() throws InterruptedException { 
         System.out.println("start " + index); 
         Thread.sleep(1000); // pretend to do work 
         System.out.println("stop " + index); 
         return null; 
        } 
       } 
      ); 
    } 
} 

उत्तर

10

यह निष्पादक वांछित नीति के साथ SynchronousQueue द्वारा समर्थित तरह लग रहा है कि आप क्या चाहते है:

executor = new ThreadPoolExecutor(
    1, 1, 
    1000, TimeUnit.SECONDS, 
    new SynchronousQueue<Runnable>(), 
    new ThreadPoolExecutor.DiscardPolicy()); 
+0

बदल गया है Coudl तुम मुझे बताओ, आप एक कारण है कि उपयोग करने को प्राथमिकता अन्य धागे 'ढेर करने के लिए सेमाफोर संदर्भ से प्रसारित है अस्वीकृत निष्पादन निष्पादन को पकड़ने पर नीति को छोड़ दें? –

0

अगर कोई कतार नहीं है, एक निष्पादक मैं कहेंगे की कोई जरूरत नहीं है। अकेले एक सेमफोर का उपयोग करना पर्याप्त लगता है। मैं उसी कोड को चलाने से बचने के लिए नीचे दिए गए कोड का उपयोग कर रहा हूं जब यह पहले से चल रहा है। बस सुनिश्चित semaphorestatic volatile, जो वर्ग के लिए सेमाफोर केवल सेमाफोर बनाता है और जैसे ही यह

if (this.getSemaphore().tryAcquire()) { 
     try { 
      process(); 
     } catch (Exception e) { 
     } finally { 
      this.getSemaphore().release(); 
     } 
} 
else { 
    logger.info(">>>>> Job already running, skipping go"); 
} 
+0

कार्य को एक अलग थ्रेड में चलाने की आवश्यकता है ताकि मुख्य धागा अवरुद्ध न हो या अन्यथा प्रभावित न हो ("मुख्य रेखा" वास्तव में एक स्विंग ऐप है) –