2015-05-27 24 views
8
synchronized (Foo.class) { 
    while (someCondition) { 
     try { 
      Foo.class.wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace();    
     } 
    } 
} 

Dường như cả hai chủ đề này đều được đánh thức khi một số chủ đề khác gọi interrupt() hoặc notify() về chủ đề này. Có sự khác biệt nào giữa hai người không?Sự khác nhau giữa chờ/thông báo và chờ/ngắt là gì?

--EDIT--

Tôi biết một là để thông báo cho đối tượng, người kia ngắt chuỗi. Nhưng cả hai đều dẫn đến cùng một hệ quả, đó là, chủ đề này được đánh thức, vì vậy điều tôi muốn hỏi là hậu quả của 2 tình huống này khác nhau như thế nào.

+3

[Tài liệu 'Thread'] (http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html) và [' Object' documentation] (http: // docs. oracle.com/javase/8/docs/api/java/lang/Object.html). –

+4

Một nguyên nhân là một ngoại lệ, trường hợp khác gây ra sự trở lại. Một thông báo cho một đối tượng, cái kia ngắt một luồng. Một là quả táo, quả còn lại là quả cam. – EJP

+1

Thức dậy không phải là hậu quả duy nhất, như bạn sẽ thấy trong tài liệu. –

Trả lời

3

Khi một chuỗi gọi thông báo trên một số màn hình, nó sẽ đánh thức một chuỗi duy nhất đang chờ trên màn hình đó, nhưng mà chủ đề được đánh số là được lập lịch biểu. (Hoặc một thread có thể gọi notifyAll, mà đánh thức tất cả các chủ đề chờ đợi cho màn hình đó, sau đó tất cả đều tranh giành cho màn hình, sau đó những kẻ thua cuộc quay trở lại chờ đợi.) Đó là lý do tại sao mục tiêu của cuộc gọi là khác nhau, thông báo được thực hiện vào màn hình, thông báo cho trình lên lịch để chọn một chuỗi để đánh thức.

Không giống như thông báo, mục tiêu gián đoạn sẽ là một chuỗi cụ thể. Và gián đoạn không yêu cầu chuỗi bị gián đoạn phải đợi trên màn hình. Đối với một chủ đề để gọi chờ đợi trên một màn hình nó đã có được mua màn hình đầu tiên, sau đó chờ đợi phát hành theo dõi cho đến khi thread được thực hiện chờ đợi hoặc bị gián đoạn.

Đề xuất của Oracle chỉ sử dụng gián đoạn để hủy. Ngoài ra các lớp trong java.util.concurrent được thiết kế để sử dụng ngắt để hủy bỏ. Trong trường hợp gián đoạn ví dụ của bạn sẽ không hiệu quả lắm, bởi vì điều khiển không rời khỏi vòng lặp while, luồng vẫn phải kiểm tra tình trạng nó đang chờ, và không có kiểm tra trong điều kiện vòng lặp while cho dù ngắt cờ được đặt. Có khả năng là chuỗi bị gián đoạn sẽ quay lại ngay để chờ đợi.

Để làm cho mã này thoát khi nó bị gián đoạn, thay vì quay lại chờ, hãy thêm kiểm tra trạng thái cờ bị gián đoạn vào điều kiện vòng lặp và có khối catch đặt cờ ngắt (được đặt lại khi ngoại lệ được ném):

synchronized (Foo.class) { 
    while (someCondition && !Thread.currentThread().isInterrupted()) { 
     try { 
      Foo.class.wait(); 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt();    
     } 
    } 
} 
0
  1. phương pháp Chờ được sử dụng để đình chỉ một sợi hiện hành về một đối tượng. Phương pháp chờ không phải từ lớp chuỗi nhưng từ java.lang.Object

  2. Phương thức thông báo được sử dụng để đánh thức luồng đang chờ đối tượng. Phương thức thông báo không phải từ lớp chuỗi nhưng từ java.lang.Object.

  3. Phương pháp ngắt được sử dụng để cho biết luồng hiện tại là nên dừng thực hiện công việc hiện tại và có thể bắt đầu công việc khác. Phương thức ngắt là từ lớp chuỗi.

Hãy thử xem các ví dụ thực tế đời sống:

Cân nhắc điện thoại như Object, Person như chủ đề. Giả sử ví dụ Một người đang sử dụng điện thoại và người B cũng muốn sử dụng điện thoại nhưng với tư cách là một người (Chủ đề 1) đang bận sử dụng trừ khi công việc được thực hiện mua một khóa trên điện thoại Object now B i.e (Chủ đề 2) cố gắng sử dụng Điện thoại nhưng khi A đã mua khóa trên nó, B sẽ chuyển sang trạng thái đợi cho đến khi khóa được giải phóng.

  • Nếu đối tượng điện thoại gọi phương thức chờ, nó sẽ giới hạn chủ đề hiện tại muốn sử dụng Điện thoại và nó sẽ chuyển sang trạng thái chờ.
  • Nếu các cuộc gọi đối tượng điện thoại thông báo, nó sẽ báo hiệu luồng đang chờ trên nó để lấy khóa và tiến hành công việc dự định.
  • Nếu người A (chủ đề 1) đang sử dụng đối tượng điện thoại và đang thực hiện một số nhiệm vụ nhưng phương thức ngắt được gọi thì A sẽ được báo hiệu dừng bằng nhiệm vụ hiện tại và có thể cần thực hiện một số nhiệm vụ khác được gán.
1

Về cơ bản, bạn không tìm kiếm sự khác biệt về sách văn bản nhưng khác biệt trong trường hợp sử dụng của chúng.

Như folks đã đã chỉ ra, thức dậy thread không phải là hậu quả duy nhất nhưng gọi t1.interrupt() từ Chủ đề t2 cho t1 sẽ gây ra một InterruptedException trong chủ đề t1 và đó là một sự khác biệt lớn giữa Object.notify()Thread.interrupt().

Bạn nên hiểu rằng phương pháp của nó Object.wait() mà ném kiểm tra InterruptedException và buộc bạn phải xử lý nó. Object.wait.

Ngắt gián đoạn - nếu bất kỳ chủ đề nào bị gián đoạn luồng hiện tại trước hoặc trong khi luồng hiện tại đang chờ thông báo. Trạng thái bị gián đoạn của chuỗi hiện tại sẽ bị xóa khi trường hợp ngoại lệ này bị ném.

Sau đó, bạn nên tham khảo this question để có ý tưởng về cách xử lý ngoại lệ này.

Sự khác biệt giữa hai điều này nằm trong thực tế là giao tiếp giữa các luồng cho các công cụ lập trình logic thông thường (chờ & thông báo) và một (ngắt) khác là hủy bỏ/chấm dứt chuỗi ngay cả trong trường hợp chặn hoạt động. Bạn phải lưu ý rằng Java không cung cấp bất kỳ cơ chế nào để hủy trước một chuỗi để bạn phải sử dụng cơ chế ngắt cho mục đích đó (Rõ ràng, nếu cần thiết trong trường hợp của bạn), bạn có thể bỏ qua ngoại lệ này nếu không áp dụng trong trường hợp).

Java không hạn chế hành động của bạn sau InterruptedException và bạn có thể làm bất cứ điều gì bạn muốn nhưng sử dụng nó cho những thứ khác ngoài việc thực hiện Chính sách hủy bỏ chủ đề không được thông báo. Chính sách hủy bỏ chủ đề thường bị bỏ qua và ít được thảo luận hơn khi các lập trình viên viết các chương trình đa luồng và đó là lý do tại sao bạn có thể thấy khó hiểu được trường hợp sử dụng.

Phương thức API như BlockingQueue.put(..) đang cố gắng cho bạn biết bằng cách ném InterruptedException là ngay cả khi hoạt động chặn của nó cũng có thể bị chấm dứt trước. Không cần thiết rằng tất cả các phương pháp chặn API sẽ cung cấp cho bạn cơ sở đó.

Hủy/chấm dứt chuỗi bằng cách sử dụng Thread.interrupt() không phải là một cơ chế mạnh mẽ nhưng hợp tác và chỉ là yêu cầu không phải là đơn hàng.

Việc sử dụng e.printStackTrace(); của bạn không được khuyến khích vì đây thường không phải là lỗi, nếu có ý định đăng nhập dưới dạng lỗi.

Hy vọng điều đó sẽ hữu ích !!

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