2009-08-15 12 views
7

नीचे दिए गए कोड में, मैं इरादे के अनुसार 100 सेकंड के बाद टाइमआउट अपवाद पकड़ रहा हूं। इस बिंदु पर मैं कोड से मुख्य से बाहर निकलने की उम्मीद करता हूं और कार्यक्रम समाप्त हो जाता है लेकिन यह कंसोल पर प्रिंटिंग रखता है। टाइमआउट के बाद निष्पादन को रोकने के लिए मैं कार्य कैसे प्राप्त करूं?टाइमआउट अपवाद के बाद वापस आने के लिए मैं फ़्यूचरटास्क कैसे प्राप्त करूं?

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); 

private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { 
    FutureTask<T> task = new FutureTask<T>(c); 
    THREAD_POOL.execute(task); 
    return task.get(timeout, timeUnit); 
} 


public static void main(String[] args) { 

    try { 
     int returnCode = timedCall(new Callable<Integer>() { 
      public Integer call() throws Exception { 
       for (int i=0; i < 1000000; i++) { 
        System.out.println(new java.util.Date()); 
        Thread.sleep(1000); 
       } 
       return 0; 
      } 
     }, 100, TimeUnit.SECONDS); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return; 
    } 


} 

उत्तर

8

आप समय समाप्ति पर अपने कार्य को रद्द करने के लिए (और इसके धागा बीच में) की जरूरत पर निर्भर करता है के द्वारा वीएम छोड़ दिया। cancel(true) विधि यही है। :

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); 

private static <T> T timedCall(FutureTask<T> task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { 
    THREAD_POOL.execute(task); 
    return task.get(timeout, timeUnit); 
} 


public static void main(String[] args) { 
     try { 
      FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() { 
       public Integer call() throws Exception { 
         for (int i=0; i < 1000000; i++) { 
           if (Thread.interrupted()) return 1; 
           System.out.println(new java.util.Date()); 
           Thread.sleep(1000); 
         } 
         return 0; 
       } 
      }); 
      int returnCode = timedCall(task, 100, TimeUnit.SECONDS); 
     } catch (Exception e) { 
       e.printStackTrace(); 
       task.cancel(true); 
     } 
     return; 
} 
+1

! Task.cancelled() होना चाहिए! IsCancelled() djna के रूप में मूल रूप से – Zed

+1

लिखा है, मुझे लगता है कि बाधाओं का उपयोग करना बेहतर है। सबसे पहले, आपके कॉल करने योग्य कोड को 'कार्य' के बारे में जानने की आवश्यकता नहीं है। दूसरा, जब आप अपने कॉल करने योग्य कोड (जैसे 'थ्रेड.sleep()') में विभिन्न अवरुद्ध संचालन का उपयोग कर रहे हैं, तो यह task.isCancelled() पर प्रतिक्रिया नहीं करेगा, लेकिन आमतौर पर बाधाओं पर प्रतिक्रिया करता है। तो 'रद्द करें (सत्य)' का उपयोग करके और आपके कोड को बाधाओं के बारे में जागरूक करना आमतौर पर ऐसा करने का सबसे अच्छा तरीका है। (आपका कोड और भी सामान्य होगा, क्योंकि जावा में व्यवधान तंत्र का व्यापक रूप से उपयोग किया जाता है) –

+0

मुझे लगता है कि मेरा मुद्दा यह है कि "व्यवधान एक सहकारी तंत्र है।" (http://www.ibm.com/developerworks/java/library/j-jtp05236.html) –

1

एक बार जब आप TimeoutException पकड़ा, तो आप अपने कार्य के रद्द (सही) विधि कॉल करने की आवश्यकता है ...

या shutdownNow() कॉल करके अपनी ExecutorService शट डाउन ...

या System.exit (0)

बुला अपनी आवश्यकताओं

4

आपकी कॉल करने योग्य होने पर, जल्दी से रोकने में सक्षम होना चाहिए।

आपका कोड:

public Integer call() throws Exception { 
    for (int i=0; i < 1000000 && !task.cancelled(); i++) { 
     System.out.println(new java.util.Date()); 
     Thread.sleep(1000); // throws InterruptedException when thread is interrupted 
    } 
    return 0; 
} 

पहले से ही उस Thread.sleep() बुला करने के लिए धन्यवाद करने के लिए सक्षम है। प्वाइंट यह है कि futureTask.cancel(true) अन्य थ्रेड को बाधित करेगा, और आपके कोड को इस बाधा पर प्रतिक्रिया करने की आवश्यकता है। Thread.sleep() वह करता है। यदि आपने Thread.sleep() या अन्य इंटरप्टिबल ब्लॉकिंग कोड का उपयोग नहीं किया है, तो आपको अपने आप से Thread.currentThread().isInterrupted() जांचना होगा, और जितनी जल्दी हो सके छोड़ दें (उदा। new InterruptedException() फेंककर) जब आप इसे सत्य मानते हैं।

आपको अपने अपवाद हैंडलर से futureTask.cancel(true); पर कॉल करने और अपने कार्य को चलाने वाले थ्रेड को बाधित करने की आवश्यकता है।

मेरी सलाह बाधा तंत्र के बारे में जानना है (यह एक महान लेख है: Dealing with InterruptedException), और इसका उपयोग करें।

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