2012-07-28 39 views
6

Tôi đã được thông báo rằng việc sử dụng Thread.Sleep() là một giải pháp tồi vào những thời điểm mà người ta muốn thực hiện một khoảng thời gian nào đó trong một vòng lặp hành động theo phương thức được đồng bộ hóa. Mặt khác, tôi có hai luồng khác nhau đang hoạt động trong suốt thời gian chạy chương trình của tôi và cũng là một đối tượng được chia sẻ và khi tôi sử dụng Object.wait (long) trong đối tượng được chia sẻ đó, nó khiến GUI của tôi bị đóng băng trong một thời gian.Thread.Sleep thay thế trong Java

giải pháp nào tốt hơn cho vấn đề này?


Cập nhật phần này của mã là bao gồm một trong những chủ đề được bắt đầu từ năm GUI:

class temperatureUp extends Thread { @Override public void run() { while(true) { try { GBC.increaseTemp(); updateSystemStatus(); } catch(Exception ex) { StringWriter w = new StringWriter(); ex.printStackTrace(new PrintWriter(w)); txtLog.setText(w + "\n" + txtLog.getText()); } } } };

và đây là phương pháp đồng bộ trong đối tượng chia sẻ, GBC:

public synchronized void increaseTemp() throws InterruptedException{ 
    // don't increase the temperature if the boiler 
    // is not turned on... 
    while (!isBoilerOn) 
     wait(); 

    // increase the current temperature 
    if ((currentTemp + 1) < MAX_TEMP && currentTemp < desiredTemp) { 
     Thread.sleep(2000); ///what should put here if not thread sleep? 
     currentTemp ++;  
     updateGasBoilerStatus(); 
    } 
} 
+1

Bạn phải gây ra [Chủ đề gửi sự kiện] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) để chờ. Bạn có thể cung cấp một ví dụ nhỏ trong mã làm thế nào bạn bắt đầu chủ đề của bạn và khi bạn gọi wait()? – theon

+1

Hãy xem ['SwingWorker'] (http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html). Ngoài ra, xem ['this answer'] (http://stackoverflow.com/a/11546203/597657) để biết nó hoạt động như thế nào. –

+0

@theon Tôi đã cập nhật bài đăng và thêm một số phần của mã. – Afflatus

Trả lời

4

Bạn có thể thu nhỏ phạm vi của câu lệnh synchronize. Ví dụ nếu bạn đang đồng bộ hóa trên toàn bộ phương pháp

public synchronized void foo() 

Bạn có thể loại bỏ các sửa đổi và sử dụng một khối đồng bộ thay vì

synchronized (this) { 
    // ... 
} 

và di chuyển Thread.sleep() bên ngoài của khối này nếu có thể. Chỉ đồng bộ hóa trên những câu lệnh sửa đổi trạng thái của dữ liệu được chia sẻ.

Rất nhiều vấn đề về luồng liên quan đến Swing có liên quan đến Event Dispatcher Thread và có thể dễ dàng được giải quyết với nó. Tôi khuyên bạn nên đọc nó.

Một chút nền nhỏ, tại sao bạn không nên gọi Thread.sleep() bên trong một khối đồng bộ:

ngủ hoặc chờ đợi trong khi giữ một khóa. Gọi Thread.sleep với một khóa được giữ có thể ngăn chặn các luồng khác tiến hành trong thời gian dài và do đó có thể gây ra nguy cơ nghiêm trọng về khả năng sinh sản. Gọi Object.wait hoặc Condition.await với hai ổ khóa được đặt ra tương tự như nguy hiểm . [JCIP]

+1

Cảm ơn, tôi sẽ đọc bài viết trên Chủ đề sự kiện và gửi lại cho bạn trong trường hợp tôi có một câu hỏi khác. – Afflatus

+0

@Elham Trong trường hợp của bạn, tôi nghĩ rằng toàn bộ chương của * Concurrency trong Swing * sẽ giúp, vì EDT là để cập nhật các thành phần Swing và vấn đề đồng bộ hóa của bạn là về sửa đổi các trạng thái của mô hình của bạn. –

+0

thực sự phần cập nhật hoạt động tốt. vấn đề là tôi muốn làm cho nó chờ đợi sau mỗi lần cập nhật để người dùng sẽ thấy kết quả của quá trình được thực hiện theo từng chủ đề. – Afflatus

7

Đừng ngủ bên trong phương thức được đồng bộ hóa! Đừng chờ đợi trong xử lý sự kiện GUI/phương pháp!

Tách các hành động được đồng bộ hóa để cuộc gọi Sleep() không được gọi trong ngữ cảnh của luồng GUI.

Có thể sử dụng InvokeLater() cho bit thứ hai.

+0

Tôi đã vô hiệu hoá lệnh ngủ trong GUI. phương pháp đồng bộ là trong một lớp khác mà như tôi đã nói nó là một đối tượng chia sẻ đang được sử dụng bởi hai chủ đề khác nhau cùng một lúc. – Afflatus

0

Tôi sẽ sử dụng màn hình: http://www.artima.com/insidejvm/ed2/threadsynch4.html Có thể với thông báo hoặc thông báoTất cả các bạn có thể giải quyết. Chúc may mắn!

+0

Cảm ơn, nhưng điều là chờ đợi và thông báo các thread làm việc tốt trong chương trình. vấn đề của tôi là tôi muốn làm cho nó để trình bày tăng trong GUI sẽ trở nên chậm hơn cho người dùng xem. – Afflatus

0

Luôn giữ Chủ đề người gửi sự kiện (EDT) chịu trách nhiệm xử lý GUI của bạn, cách xa mọi công việc không phải giao diện người dùng.Ngoài ra, không đồng bộ hóa toàn bộ phương pháp, nhưng đồng bộ hóa những điều khoản về nguyên tử

synchronized(this){ 
    //... 
} 
+0

ok, cảm ơn nhưng làm thế nào điều này sẽ là một câu trả lời cho câu hỏi của tôi ?! – Afflatus

+0

và ba hành động duy nhất đã được đưa vào phương pháp đồng bộ của tôi là những hành động cần thiết phải nằm trong cùng một khóa trong chuỗi này. Tôi không thể thu hẹp phạm vi nữa. – Afflatus

-1

Bạn có thể thử đoạn mã sau đây:

public static void delay(int waitTime) { 
     long endTime = System.currentTimeMillis() + (waitTime * 1000); 
     while (System.currentTimeMillis() < endTime) {} 
    } 

Gọi như chậm trễ (5). Và điều khiển sẽ đợi trong 5 giây.

+0

Xin vui lòng không sử dụng này, nó là rất lộn xộn. Một thay thế sẽ là sử dụng java.util.Timer –