2012-03-14 49 views
10

Tôi có một vòng lặp chính trong chuỗi của mình, và một phần của nó kiểm tra nếu một boolean nhàn rỗi là đúng sự thật. Nếu có, nó sẽ gọi Thread.sleep(1) sau mỗi lần lặp của vòng lặp. Đây có phải là cách hiệu quả để thực hiện việc này không? Mục tiêu của tôi là cho các chủ đề để sử dụng CPU tối thiểu khi nhàn rỗi.Trong Java, có hiệu quả khi sử dụng Thread.sleep (1) cho một luồng không tải?

+0

Sẽ không mất thời gian để hệ thống liên tục hoán đổi luồng theo cách này? Nó yêu cầu sức mạnh xử lý cho trình quản lý luồng để thực hiện công việc của nó và bạn đang yêu cầu nó thực hiện công việc đó mỗi mili giây. – scriptocalypse

+0

Đó là một điều tôi nghi ngờ có thể xảy ra, nhưng tôi không chắc chắn vào thời điểm đó. Có vẻ như 'wait' và' notifyAll' sẽ thực hiện công việc tốt. – AutoBotAM

Trả lời

8

No. Sử dụng Object.wait thay vào đó và đảm bảo bạn đồng bộ hóa trên đối tượng có chứa boolean. Nếu bạn không đồng bộ hóa và boolean không phải là volatile, bạn không có rào cản bộ nhớ để không đảm bảo rằng luồng bỏ phiếu sẽ thấy thay đổi đối với boolean.

Theo javadoc:

Phương pháp này làm cho thread hiện hành (gọi nó là T) để đặt bản thân trong tập chờ đợi cho đối tượng này và sau đó để từ bỏ bất kỳ và mọi khiếu nại đồng bộ hóa trên đối tượng này. Chủ đề T trở thành tàn tật cho các mục đích đề lập kế hoạch và nằm im lìm cho đến khi một trong bốn điều sẽ xảy ra:

  • Một số chủ đề khác gọi phương thức notify cho đối tượng này và sợi T xảy ra để được tự ý chọn làm chủ đề để được đánh thức .
  • Một số luồng khác gọi phương thức notifyAll cho đối tượng này.
  • Một số chủ đề khác làm gián đoạn chủ đề T.
  • ...

để thread sẽ không có CPU trong khi nó đang chờ đợi để được thông báo.

Mã bên dưới là cờ nhàn rỗi đơn giản với phương thức waitUntilIdle mà phương thức main của bạn có thể gọi và phương thức setIdle có thể được gọi bằng một chuỗi khác.

public class IdleFlag { 
    private boolean idle; 

    public void waitUntilIdle() throws InterruptedException { 
    synchronized (this) { 
     while (true) { 
     // If the flag is set, we're done. 
     if (this.idle) { break; } 
     // Go to sleep until another thread notifies us. 
     this.wait(); 
     } 
    } 
    } 

    public void setIdle() { 
    synchronized (this) { 
     this.idle = true; 
     // Causes all waiters to wake up. 
     this.notifyAll(); 
    } 
    } 
} 
+0

Mặc dù nó sẽ hoạt động, lý do 'while (true)' nằm ngoài đồng bộ là gì? Nó sẽ chỉ kết thúc phát hành khóa và phản ứng sau khi chờ đợi (sau đó tái phát hành). Như đã đề xuất để có 'while (true)' trong các ngữ nghĩa đồng bộ, thu nhận/phát hành (chỉ một lần) cho mỗi lần chờ đợi được thông báo (thường xuyên hoặc giả). –

+1

Vâng, tôi đoán điểm của tôi là bạn có thể chỉ đơn giản là 'while' trong quá trình đồng bộ hóa mà bạn sẽ không phải chịu thêm phát hành/có được bằng cách thực hiện nó bên ngoài. Bạn nói đúng nó không có tác hại chức năng và tác động hiệu suất có thể là không đáng kể. –

+0

@JohnVint, Tốt. Đã chỉnh sửa. –

1

Tôi đồng ý với @ Mike Samuel, nhưng tôi muốn khuyên bạn nên sử dụng concurrent lock packages...

Tiếp tục với mô hình của mike chỉ cần thay thế khóa của mình với giới thiệu trong Java đặc biệt 5

hơn bạn có thể sử dụng phương pháp chờ đợi Condition's - những phương pháp mất thời gian chờ. Bằng cách đó, bạn có thể, ví dụ, đăng nhập một tin nhắn thường xuyên như vậy - một thông báo sẽ giúp bạn gỡ lỗi chờ đợi vô hạn. Bạn cũng có thể muốn thực hiện một số logic rollback nếu thời gian chờ đợi ...

+0

Có một phiên bản 'wait' mất thời gian chờ, vì vậy nếu bạn chỉ muốn nhận thời gian CPU thường xuyên để đăng nhập, việc sử dụng cuộc gọi' wait (timeout) 'dễ hơn là giới thiệu' Điều kiện '. –

+0

@ John Haager - cảm ơn vì cái nhìn sâu sắc, tôi xấu hổ khi nói rằng tôi đã không nhận thức được rằng – Yaneeve

+0

Vẫn - điều kiện liên quan đến Khóa, và chúng cho phép bạn làm những điều thú vị hơn đồng bộ đơn giản – Yaneeve

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