2010-05-12 22 views
10

मैं पहली बार वायदा का उपयोग करने की कोशिश कर रहा हूं। ऐसा लगता है कि आप नौकरी रद्द कर सकते हैं, लेकिन यह उम्मीद के अनुसार काम नहीं कर रहा है। नीचे दिए गए उदाहरण में, केवल पहला काम रद्द कर दिया गया है। बाकी पूरा हो गए हैं। क्या मैंने वायदा के उपयोग को गलत समझा है?भविष्य/थ्रेडिंग को समझना

public class ThreadExample 
{ 
    public static void main(String[] args) throws InterruptedException, ExecutionException 
    { 
     int processors = Runtime.getRuntime().availableProcessors(); 
     System.out.println("Processors: " + processors); 
     ExecutorService es = Executors.newFixedThreadPool(processors); 
     int nowork = 10; 
     Future<Integer>[] workres = new Future[nowork]; 
     for(int i = 0; i < nowork; i++) 
     { 
      workres[i] = es.submit(new SomeWork(i)); 
     } 
     for(int i = 0; i < nowork; i++) 
     { 
      if(i % 2 == 0) 
      { 
       System.out.println("Cancel"); 
       workres[i].cancel(true); 
      } 
      if(workres[i].isCancelled()) 
      { 
       System.out.println(workres[i] + " is cancelled"); 
      } 
      else 
      { 
       System.out.println(workres[i].get()); 
      } 
     } 
     es.shutdown(); 
    } 
} 

class SomeWork implements Callable<Integer> 
{ 
    private int v; 
    public SomeWork(int v) 
    { 
     this.v = v; 
    } 

    @Override 
    public Integer call() throws Exception 
    { 
     TimeUnit.SECONDS.sleep(5); 
     System.out.println(v + " done at " + (new Date())); 
     return v; 
    } 
} 

उत्पादन:

Processors: 4 
Cancel 
[email protected] is cancelled 
4 done at Wed May 12 17:47:05 CEST 2010 
2 done at Wed May 12 17:47:05 CEST 2010 
1 done at Wed May 12 17:47:05 CEST 2010 
3 done at Wed May 12 17:47:05 CEST 2010 
1 
Cancel 
2 
3 
Cancel 
4 
5 done at Wed May 12 17:47:10 CEST 2010 
7 done at Wed May 12 17:47:10 CEST 2010 
8 done at Wed May 12 17:47:10 CEST 2010 
6 done at Wed May 12 17:47:10 CEST 2010 
5 
Cancel 
6 
7 
Cancel 
8 
9 done at Wed May 12 17:47:15 CEST 2010 
9 

उत्तर

7

समस्या यह है कि आपका रद्दीकरण लूप आपके get() लूप के साथ ओवरलैप कर रहा है, जो ब्लॉक करता है। मुझे लगता है कि आप 2 लूप चाहते हैं, है ना? एक लूप जो संख्याबद्ध नौकरियों को रद्द करता है, और फिर दूसरा लूप जो जांचता है कि कौन से रद्द किए गए हैं और कौन से नहीं हैं, और उसके बाद get() तदनुसार।

जिस तरह से यह अभी लिखा है, इससे पहले कि पाश भी workres[2] को रद्द करने का मौका मिला है, यह जाँच की और workres[1] से get() के लिए कहा।

तो मैं आप 3 चरणों की जरूरत है:

1. The `submit()` loop 
2. The selective `cancel()` loop 
3. The selective `get()` loop (which blocks) 
+0

धन्यवाद! प्राप्त करने के बारे में नहीं सोचा() एक ऐसी विधि है जो किसी समस्या को अवरुद्ध करता है। –

8

Future#cancel() समाप्त नहीं होगा/पहले से चल रहा नौकरियों बीच में। यह केवल अभी तक चल रही नौकरियों को रद्द नहीं करेगा।

अद्यतन: polygenelubricants जड़ किसी न किसी नीचे का कारण (+1): यहां बेहतर कोड है:

int processors = Runtime.getRuntime().availableProcessors(); 
System.out.println("Processors: " + processors); 
ExecutorService es = Executors.newFixedThreadPool(processors); 
int nowork = 10; 
Future<Integer>[] workers = new Future[nowork]; 

for (int i = 0; i < nowork; i++) { 
    final int ii = i; 
    workers[i] = es.submit(new Callable<Integer>() { 
     public Integer call() throws Exception { 
      return ii; 
     } 
    }); 
} 

for (int i = 0; i < nowork; i++) { 
    if (i % 2 == 0) { 
     System.out.println("Cancel worker " + i); 
     workers[i].cancel(true); 
    } 
} 

for (int i = 0; i < nowork; i++) { 
    if (workers[i].isCancelled()) { 
     System.out.println("Worker " + i + " is cancelled"); 
    } else { 
     System.out.println("Worker " + i + " returned: " + workers[i].get()); 
    } 
} 

es.shutdown(); 

परिणाम:

 
Processors: 2 
Cancel worker 0 
Cancel worker 2 
Cancel worker 4 
Cancel worker 6 
Cancel worker 8 
Worker 0 is cancelled 
Worker 1 returned: 1 
Worker 2 is cancelled 
Worker 3 returned: 3 
Worker 4 is cancelled 
Worker 5 returned: 5 
Worker 6 is cancelled 
Worker 7 returned: 7 
Worker 8 is cancelled 
Worker 9 returned: 9 

(ध्यान दें कि यह workers है, है ना workres) ।

+0

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

+0

मुझे खुद को 'रद्द करें' और 'इंटरप्ट' (या 'abort' या' terminate') के बीच का अंतर मिलता है। अभी तक पर्याप्त स्पष्ट है। – BalusC

+0

आप एक ऐसी नौकरी को मजबूर करने के लिए '.cancel (true)' को कॉल कर सकते हैं जिसने बाधा डालना शुरू कर दिया है। – Finbarr

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