2010-05-12 9 views
10

Tôi đang cố gắng sử dụng tương lai lần đầu tiên. Nó có vẻ thông minh mà bạn có thể hủy bỏ một công việc, nhưng nó không hoạt động như mong đợi. Trong ví dụ dưới đây, chỉ có công việc đầu tiên bị hủy. Phần còn lại được hoàn thành. Tôi đã hiểu lầm việc sử dụng tương lai chưa?Tìm hiểu về tương lai/luồng

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; 
    } 
} 

Sản lượng:

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 

Trả lời

7

Vấn đề là vòng hủy của bạn bị chồng chéo với vòng lặp get() của bạn. Tôi nghĩ bạn muốn có 2 vòng, phải không? Một vòng lặp hủy ngay cả các công việc được đánh số, và sau đó là một vòng lặp thứ hai để kiểm tra xem các công việc nào bị hủy và các vòng lặp nào không, và sau đó là get() tương ứng.

Cách viết ngay bây giờ, trước khi vòng lặp thậm chí có cơ hội hủy workres[2], nó đã kiểm tra và yêu cầu get() từ workres[1].

Vì vậy, tôi nghĩ rằng bạn cần làm 3 giai đoạn:

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

Cảm ơn! Đã không nghĩ về get() là một phương pháp chặn một vấn đề. –

8

Các Future#cancel() sẽ không chấm dứt/làm gián đoạn đang chạy việc làm. Nó sẽ chỉ hủy các công việc chưa chạy.

Cập nhật: polygenelubricants đóng đinh gốc gây xuống (+1): đây là mã được cải tiến:

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(); 

Kết quả:

 
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 

(lưu ý rằng nó workers, không workres) .

+0

"Nếu nhiệm vụ đã bắt đầu, sau đó tham số mayInterruptIfRunning xác định xem chủ đề thực hiện nhiệm vụ này nên bị gián đoạn trong một nỗ lực để ngăn chặn các nhiệm vụ." Imo hủy là một từ/phương thức rất xấu để sử dụng nếu bạn chỉ có thể sử dụng nó trên các công việc chưa chạy:/ –

+0

Bản thân tôi tìm thấy sự khác biệt giữa 'cancel' và' interrupt' (hoặc 'abort' hoặc' terminate') chưa đủ rõ ràng. – BalusC

+0

Bạn có thể gọi '.cancel (true)' để buộc một công việc đã bắt đầu bị gián đoạn. – Finbarr