2010-09-23 37 views
6

Tôi đang viết một ứng dụng sinh ra nhiều tác vụ đồng thời. Tôi đang sử dụng một hồ bơi thread để thực hiện điều đó.làm thế nào để ngăn chặn một sợi trong một threadpool

Có thể xảy ra sự kiện xảy ra làm cho các tính toán được thực hiện trong các tác vụ không hợp lệ. Trong trường hợp đó, tôi muốn dừng các tác vụ hiện đang chạy và bắt đầu các tác vụ mới.

Vấn đề của tôi: Làm thế nào để dừng các tác vụ hiện đang chạy? Giải pháp mà tôi đã triển khai là lưu trữ một tham chiếu đến chuỗi nhiệm vụ và gọi interrupt() về chủ đề này. Trong code demo:

public class Task implements Runnable { 

    private String name; 
    private Thread runThread; 

    public Task(String name) { 
     super(); 
     this.name = name; 
    } 

    @Override 
    public void run() { 
     runThread = Thread.currentThread(); 

     System.out.println("Starting thread " + name); 
     while (true) { 
      try { 
       Thread.sleep(4000); 
       System.out.println("Hello from thread " + name); 
      } catch (InterruptedException e) { 
       // We've been interrupted: no more messages. 
       return; 
      } 
     } 
    } 

    public void stop() { 
     runThread.interrupt(); 
    } 

    public String getName() { 
     return name; 
    } 
} 

Và phương pháp chính là:

public static void main(String args[]) { 
    executorService = Executors.newFixedThreadPool(2); 

    Task t1 = new Task("Task1"); 
    Task t2 = new Task("Task2"); 
    executorService.execute(t1); 
    executorService.execute(t2); 
    executorService.execute(new Task("Task3")); 
    executorService.execute(new Task("Task4")); 

    try { 
     Thread.sleep(12000); 
     t1.stop(); 
     System.err.println("Stopped thread " + t1.getName()); 
     Thread.sleep(8000); 
     t2.stop(); 
     System.err.println("Stopped thread " + t2.getName()); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

Đây có phải là một giải pháp tốt, hoặc là có một cách tốt hơn để ngăn chặn một thread chạy trong một hồ bơi thread?

+1

Kéo phích cắm;) – sje397

Trả lời

2

Trong phương pháp được ghi đè run() bạn lặp lại vĩnh viễn với while(true). Hành vi chuẩn sẽ có một phương thức boolean runIndicator mà phương thức run() đặt thành true khi bắt đầu và vòng lặp của bạn sẽ là while(runIndicator). Phương thức stop() của bạn nên được thiết lập đơn giản runIndicator = false do đó vòng lặp tiếp theo của vòng lặp sẽ bị loại bỏ.

+0

Trong triển khai này, phương thức 'stop()' cũng nên gọi 'this.interrupt()'. Trong thực tế thực tế, cần có một phương pháp tương tự mà bạn có thể sử dụng để ngăn chặn bất kỳ việc nâng hạng nặng nào đang diễn ra thay vì cuộc gọi 'Thread.sleep * (4000)'. Bạn có thể sử dụng một phương thức rất giống với 'runIndicator' để thực hiện điều này. –

+0

@Erick, 'ngắt()' không phải là một phương thức runnable, vì vậy điều này là không thể. 'Thread.currentThread(). Interrupt()' sẽ không hoạt động hoặc vì việc gọi dừng() xảy ra trong một luồng khác với chuỗi bạn muốn ngắt. – Thirler

+1

Xin lỗi, tôi không hiểu. Tôi luôn mở rộng 'Thread' thay vì' Runnable', vì vậy tôi luôn có quyền truy cập vào những thứ này. Tôi sẽ làm như vậy ở đây. Điều này cũng sẽ giải quyết vấn đề chủ đề nhỏ mà bạn đã đăng trong câu trả lời của mình. –

3

Ý tưởng đằng sau cách tiếp cận của bạn là một trong nhiều giải pháp chính xác. Dealing with InterruptedException cho một tóm tắt tuyệt vời về cách bạn nên sử dụng cơ chế ngắt. Cơ chế này chủ yếu hữu ích khi bạn tính toán dài. Một điều khác cần lưu ý là có thể cho các thư viện khác làm hỏng cơ chế ngắt của bạn bằng cách không làm những gì hướng dẫn nói (không đặt lại trạng thái ngắt khi chúng chưa xử lý nó).

Lưu ý rằng lớp Task của bạn không an toàn cho chủ đề. Bạn có thể dừng công việc trước khi lưu currentThread, điều này sẽ cung cấp cho NullPointerException.

Cách tiếp cận đơn giản hơn nhiều là đặt một biến số volatile booleanrunning và thay vì một vòng lặp while(true) làm cách tiếp cận while(running) (điều này tuy nhiên tổng quát hơn nhiều).

Một điều cần xem xét là cơ chế FutureTask, vì điều này đã có cơ chế hủy sử dụng cơ chế ngắt.

1

executorService.shutdown() và executorService.shutdownNow() nên được sử dụng để tắt hồ bơi luồng để thoát khỏi ứng dụng một cách duyên dáng. Xem ExecutorService.

Xem câu trả lời của Qwerky để kết thúc chuỗi hiện đang chạy.

+4

Anh ấy muốn tắt một chủ đề duy nhất, không phải toàn bộ hồ bơi. –

+0

Câu trả lời đó được đưa ra bởi Qwerky. Nhưng tắt hồ bơi thread cũng được yêu cầu để thoát khỏi ứng dụng một cách duyên dáng. –

2

Bạn có thể ngăn chặn nó bằng cách giữ một tham chiếu đến tương lai mà

  Future<?> future = exec.submit(new Runnable() { 
     while (true){ 
     try{ 
      obj.wait(); 
     }catch(InterruptedException e){ 
      System.out.println("interrupted"); 
      return; 
     } 
     }); 
     future.cancel(true); 

boolean là cho - thể làm gián đoạn nếu chạy.

Tôi đã kiểm tra và có ngoại lệ bị gián đoạn từ chuỗi đó.

Nếu bạn đã lưu trong bộ nhớ cacheThreadPool, bạn có thể muốn kiểm tra lại xem bạn có bị ngoại lệ trong runnable không, và sau đó không đặt lại cờ bị gián đoạn, vì chuỗi của bạn sẽ chạy một tương lai khác, nếu bạn đặt ngắt, hàng đợi khác tương lai có thể không chạy.

Các vấn đề liên quan