2012-06-22 11 views
6

Tôi đẩy tương lai của tôi từ một ExecutorService vào một bản đồ băm. Sau đó, tôi có thể gọi hủy trên Futures từ bên trong bản đồ băm. Mặc dù kết quả là đúng, sau đó tôi nhấn breakpoint trong thủ tục Callable, như thể hủy Future() không có hiệu lực. . Tôi nghĩ rằng nó có thể là một trường hợp của hai tài liệu tham khảo khác nhau ở đây (mặc dù các ID tài liệu tham khảo được liệt kê như là tương tự khi breakpointing), nhưng đã tự hỏi nếu một số chuyên gia có thể kêu vang trong Đây là những gì mã trông giống như:Nhiệm vụ tương lai của ExecutorService không thực sự hủy bỏ

ExecutorService taskExecutor = Executors.newCachedThreadPool(); 
Map <String, Future<Object>> results = new HashMap <String, Future<Object>>();  

Future<Object> future = taskExecutor.submit(new MyProcessor(uid)); 
results.put(uid, future); 

tôi cho phép xử lý để tiếp tục (đó là một vòng lặp mà nộp nhiệm vụ khi chúng được thông qua năm), và sau đó tôi có thể cố gắng để hủy bỏ từ một nguồn bên ngoài bằng cách gọi phương pháp này:

public static synchronized boolean cancelThread(String uid) { 
    Future<Object> future = results.get(uid); 
    boolean success = false; 
    if (future != null) { 
     success = (future.isDone() ? true : future.cancel(true)); 
     if (success) 
      results.remove(uid); 
    } 
    return success;  
} 

Nhưng tôi vẫn gặp một "phi -cố "đường dẫn trong MyProcessor.call() sau khi hàm tương lai.cancel() được gọi - nghĩa là nó không thực sự bị hủy bỏ.

Tôi sẽ làm gì sai với điều này? Có cách nào tốt hơn để làm điều này?

Trả lời

13

Sau đó tôi nhấn điểm ngắt trong quy trình Gọi, như thể hủy Tương lai() không có hiệu lực.

Future.cancel(true) xóa công việc nằm trong hàng đợi và chưa chạy nhưng nếu công việc đang chạy nó tương đương với Thread.interrupt(). Điều này đặt bit ngắt trên luồng và gây ra bất kỳ sleep(), wait() và một số phương thức khác để ném InterruptedException.

Điều quan trọng là nhận ra rằng nó không dừng chuỗi. Bạn cần chủ động kiểm tra cờ ngắt trong vòng lặp chuỗi của bạn hoặc xử lý đúng cách InterruptedException.

Xem SO tôi trả lời vào đây để biết thêm chi tiết:

how to suspend thread using thread's id?

+0

Cũng liên quan đến: http://stackoverflow.com/questions/6698977/thread-interrupt-will-it-cancel-oncoming-wait-call – Gray

+0

Tôi hiểu, điều đó có nghĩa - tôi không phải chờ đợi () trạng thái tại thời điểm này trong lần gọi thứ hai, vì vậy nó không ném InterruptedException cho tôi. Thật không may, những gì tôi đang cố gắng để hủy bỏ là một cuộc gọi tuyên bố duy nhất đến một cơ sở dữ liệu một khi nó đã bắt đầu, vì vậy tốt nhất tôi có thể đặt một thử nghiệm cho nếu thread bị gián đoạn sau đó. –

+0

Để làm rõ, đây là tuyên bố tôi có khả năng trong khi yêu cầu hủy bỏ, một PreparedStatement vào cơ sở dữ liệu: 'stmt.execute();' Vì vậy, tôi đoán tôi phải để cho khóa học kết thúc cơ sở dữ liệu, và kiểm tra gián đoạn sau đó. –

0

FutureTask :: boolean cancel(boolean mayInterruptIfRunning) sẽ thực hiện interrupt trên sợi chạy hiện hành.

FutureTask.java 
public boolean cancel(boolean mayInterruptIfRunning) { 
    if (!(state == NEW && 
      UNSAFE.compareAndSwapInt(this, stateOffset, NEW, 
       mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) 
     return false; 
    try { // in case call to interrupt throws exception 
     if (mayInterruptIfRunning) { 
      try { 
       Thread t = runner; 
       if (t != null) 
        t.interrupt();  ////////////HERE///////////// 
      } finally { // final state 
       UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); 
      } 
     } 
    } finally { 
     finishCompletion(); 
    } 
    return true; 
} 

JavaDoc cho biết dưới đây để biết interrupt

public void ngắt()

Ngắt chủ đề này. Trừ khi chủ đề hiện tại bị gián đoạn, điều này luôn được cho phép, phương thức checkAccess của chủ đề này được gọi, có thể gây ra một lỗi SecurityException.

Nếu chủ đề này bị chặn trong yêu cầu chờ đợi(), chờ (dài), hoặc chờ (dài, int) phương pháp của lớp Object hoặc tham gia(), tham gia (dài), tham gia (dài, int), ngủ (dài), hoặc ngủ (dài, int), phương pháp của lớp này, sau đó trạng thái ngắt của nó sẽ bị xóa và nó sẽ nhận được một gián đoạn ngoại lệ.

Nếu luồng này bị chặn trong hoạt động I/O khi kênh gián đoạn thì kênh sẽ bị đóng, trạng thái ngắt của luồng sẽ được đặt và luồng sẽ nhận được ClosedByInterruptException.

Nếu thread này bị chặn trong một Selector sau đó tình trạng ngắt của chủ đề sẽ được thiết lập và nó sẽ trở lại ngay lập tức từ các hoạt động lựa chọn , có thể với một giá trị khác không, cũng giống như khi phương pháp wakeup của selector được gọi .

Nếu không có điều kiện nào trước đó được giữ thì trạng thái ngắt của luồng này sẽ được đặt.

Việc gián đoạn luồng không còn hoạt động không cần phải có hiệu lực.

Ném: SecurityException - nếu xử lí hiện tại không thể sửa đổi chủ đề này

Để kết luận; hủy bỏ FutureTask chỉ tác động nếu luồng bị chặn (trong yêu cầu chờ đợi(), ...) nếu không, nhà phát triển có trách nhiệm kiểm tra Thread.currentThread().isInterrupted() để thoát; trong khi thực hiện thao tác không bị chặn.