Java: Ngắt và kết nối Thread

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Ngắt (Interrupt)

Ngắt là một dấu hiệu cho một luồng mà nó nên dừng lại những gì nó đang làm và làm những thứ khác nữa. Lập trình viên sẽ quyết định chính xác cách một luồng phản ứng với ngắt như thế nào, nhưng việc kết thúc luồng là rất phổ biến. Đây là cách sử dụng được đề cập đến trong bài học này.

Một luồng gửi một ngắt bằng cách gọi interrupt trên đối tượng Thread để ngắt luồng. Để làm việc một cách chính xác, luồng bị ngắt phải hỗ trợ ngắt của chính nó.

Hỗ trợ ngắt

Làm thế nào để một luồng hỗ trợ ngắt của riêng nó? Điều này phụ thuộc vào những gì nó hiện đang làm. Nếu luồng thường xuyên gọi các phương thức để ném InterruptedException, thì nó chỉ đơn giản là trả về từ phương thức run() sau khi nó bắt được ngoại lệ đó. Ví dụ, giả sử rằng việc lặp thông điệp trung tâm trong ví dụ SleepMessages nằm trong phương thức run() của đối tượng Runnable của luồng. Sau đó, nó có thể được sửa đổi như sau để hỗ trợ ngắt:

for(int i=0;i<importantInfo.length;i++){
  // Dừng 4 giây
  try{
    Thread.sleep(4000);
  }catch(InterruptedException e){
    // Đã được ngắt: không có thông báo nào.
    return;
  }
  // In thông báo
  System.out.println(importantInfo[i]);
}

Nhiều phương thức ném InterruptedException, chẳng hạn như sleep(), được thiết kế để hủy bỏ hoạt động hiện thời của chúng và trả về tức thì khi nhận được ngắt.

Điều gì sẽ xảy ra nếu một chuỗi hoạt động trong một thời gian dài mà không gọi một phương thức ném InterruptedException? Khi đó, nó phải định kỳ gọi Thread.interrupted, nó sẽ trả về true nếu một ngắt đã được nhận. Ví dụ:

for(int i=0;i<inputs.length;i++){
  heavyCrunch(inputs[i]);
  if(Thread.interrupted()){
    // Đã được ngắt
    return;
  }
}

Trong ví dụ đơn giản trên, mã lệnh đơn giản là sẽ kiểm tra ngắt và thoát ra khỏi luồng nếu nó đa được nhận. Trong các ứng dụng phức tạp hơn người ta thường ném một InterruptedException:

if(Thread.interrupted()){
  throw new InterruptedException();
}

Điều này cho phép xử lý mã ngắt được tập trung trong một mệnh đề catch.

Cờ trạng thái ngắt

Các cơ chế ngắt được thực hiện bằng một cờ bên trong được gọi là trạng thái ngắt. Lời gọi tới phương thức Thread.interrupt() sẽ thiết lập cờ này. Khi một luồng kiểm tra ngắt bằng cách gọi phương thức tĩnh Thread.interrupted, thì trạng thái ngắt sẽ được xóa. Phương thức không tĩnh isInterrupted() được sử dụng bởi một luồng để truy vấn trạng thái ngắt của luồng khác, và không làm thay đổi cờ trạng thái ngắt.

Theo quy ước, bất kỳ phương thức nào thoát ra bằng cách ném một ngoại lệ InterruptedException để xóa tình trạng ngắt khi nó gây ra. Tuy nhiên, luôn có khả năng trạng thái ngắt được thiết lập tức thì bởi một luồng khác đang gọi interrupt.

Kết nối (Join)

Phương thức join() cho phép một luồng chờ một luồng khác thực thi xong. Nếu t là một đối tượng Thread và hiện tại nó đang thực thi,

t.join();

thì sẽ làm cho luồng hiện thời tạm dừng thực thi cho đến khi chấm dứt luồng t. Việc tải chồng phương thức join() cho phép lập trình viên xác định thời gian chờ. Tuy nhiên, cũng như sleep(), join() phụ thuộc vào hệ điều hành về thời gian, vì vậy bạn không nên nghĩ rằng join() sẽ chờ đợi chính xác trừ khi bạn chỉ định.

Giống như sleep(), join() phản hồi với một ngắt bằng cách thoát với một ngoại lệ InterruptedException.

» Tiếp: Ví dụ SimpleThreads
« Trước: Dừng thực thi với phương thức Thread.sleep()
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!